diff --git a/packages/react/src/components/ComboBox/ComboBox.test.tsx b/packages/react/src/components/ComboBox/ComboBox.test.tsx
index df3c38448816a..74e3e6ba8188d 100644
--- a/packages/react/src/components/ComboBox/ComboBox.test.tsx
+++ b/packages/react/src/components/ComboBox/ComboBox.test.tsx
@@ -1,25 +1,16 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
-import { ReactWrapper } from 'enzyme';
-import { render } from '@testing-library/react';
+import { render, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import { safeCreate, safeMount } from '@fluentui/test-utilities';
-
import { isConformant } from '../../common/isConformant';
-import { Autofill } from '../../Autofill';
import { useKeytipRef } from '../../Keytips';
import { SelectableOptionMenuItemType } from '../../SelectableOption';
-import { KeyCodes, resetIds } from '../../Utilities';
+import { resetIds } from '../../Utilities';
import { ComboBox } from './ComboBox';
import type { IComboBox, IComboBoxOption } from './ComboBox.types';
-const OPTION_SELECTOR = '.ms-ComboBox-option';
-const CHECKBOX_OPTION = OPTION_SELECTOR + ' > input';
-const BUTTON_OPTION = 'button' + OPTION_SELECTOR;
-const OPEN_SELECTOR = '.is-open';
-
const RENDER_OPTIONS: IComboBoxOption[] = [
{ key: 'header', text: 'Header', itemType: SelectableOptionMenuItemType.Header },
{ key: '1', text: 'Option 1' },
@@ -54,14 +45,6 @@ const RUSSIAN_OPTIONS: IComboBoxOption[] = [
const returnUndefined = () => undefined;
-const createNodeMock = (el: React.ReactElement<{}>) => {
- return {
- __events__: {},
- addEventListener: () => undefined,
- removeEventListener: () => undefined,
- };
-};
-
describe('ComboBox', () => {
const createPortal = ReactDOM.createPortal;
@@ -69,13 +52,6 @@ describe('ComboBox', () => {
(ReactDOM as any).createPortal = (node: any) => node;
}
- beforeAll(() => {
- // Certain later tests mock ReactDOM.createPortal.
- // Since this is the first test to call mount(), we have to mount something with the real
- // version of createPortal first to allow some global setup to run properly (enzyme quirk/bug).
- safeMount(
);
- });
-
beforeEach(() => {
resetIds();
});
@@ -90,14 +66,8 @@ describe('ComboBox', () => {
});
it('Renders correctly', () => {
- safeCreate(
- ,
- component => {
- const tree = component.toJSON();
- expect(tree).toMatchSnapshot();
- },
- { createNodeMock },
- );
+ const { container } = render();
+ expect(container).toMatchSnapshot();
});
it('Renders correctly when open', () => {
@@ -105,24 +75,22 @@ describe('ComboBox', () => {
mockCreatePortal();
const ref = React.createRef();
- safeMount(, wrapper => {
- ref.current!.focus(true);
- wrapper.update();
- // Unlike react-test-renderer's toJSON, snapshots of DOM nodes don't include event handlers
- // and have a few other differences, but it's a decent tradeoff since react-test-renderer
- // doesn't support refs and makes it hard/impossible to open the ComboBox for a snapshot.
- expect(wrapper.getDOMNode()).toMatchSnapshot();
- });
+ const { container, getByRole } = render(
+ ,
+ );
+ userEvent.click(getByRole('combobox'));
+ expect(container).toMatchSnapshot();
});
it('Renders correctly when opened in multi-select mode', () => {
mockCreatePortal();
const ref = React.createRef();
- safeMount(, wrapper => {
- ref.current!.focus(true);
- wrapper.update();
- expect(wrapper.getDOMNode()).toMatchSnapshot();
- });
+ const { container, getByRole } = render(
+ ,
+ );
+
+ userEvent.click(getByRole('combobox'));
+ expect(container).toMatchSnapshot();
});
it('renders with a Keytip correctly', () => {
@@ -136,42 +104,32 @@ describe('ComboBox', () => {
return ;
};
- safeMount(, wrapper => {
- expect(wrapper.getDOMNode()).toMatchSnapshot();
- });
+ const { container } = render();
+ expect(container).toMatchSnapshot();
});
it('Can flip between enabled and disabled.', () => {
- safeMount(, wrapper => {
- expect(wrapper.find('.ms-ComboBox.is-disabled')).toHaveLength(0);
- expect(wrapper.find('input[data-is-interactable=true]')).toHaveLength(1);
+ const { getByRole, rerender } = render();
+ const combobox = getByRole('combobox');
+ expect(combobox.getAttribute('aria-disabled')).toEqual('false');
- wrapper.setProps({ disabled: true });
-
- expect(wrapper.find('.ms-ComboBox.is-disabled')).toHaveLength(1);
- expect(wrapper.find('input[data-is-interactable=false]')).toHaveLength(1);
- });
+ rerender();
+ expect(combobox.getAttribute('aria-disabled')).toEqual('true');
});
it('Renders no selected item in default case', () => {
- safeCreate(, container => {
- const input = container.root.findByType('input');
- expect(input.props.value).toEqual('');
- });
+ const { getByRole } = render();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('');
});
it('Renders a selected item in uncontrolled case', () => {
- safeCreate(, container => {
- const input = container.root.findByType('input');
- expect(input.props.value).toEqual('1');
- });
+ const { getByRole } = render();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('1');
});
it('Renders a selected item in controlled case', () => {
- safeCreate(, container => {
- const input = container.root.findByType('input');
- expect(input.props.value).toEqual('1');
- });
+ const { getByRole } = render();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('1');
});
it('Renders a selected item with zero key', () => {
@@ -179,10 +137,8 @@ describe('ComboBox', () => {
{ key: 0, text: 'zero' },
{ key: 1, text: 'one' },
];
- safeCreate(, container => {
- const input = container.root.findByType('input');
- expect(input.props.value).toEqual('zero');
- });
+ const { getByRole } = render();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('zero');
});
it('changes to a selected key change the input', () => {
@@ -190,14 +146,11 @@ describe('ComboBox', () => {
{ key: 0, text: 'zero' },
{ key: 1, text: 'one' },
];
- safeMount(, wrapper => {
- expect(wrapper.find('input').props().value).toEqual('zero');
-
- wrapper.setProps({ selectedKey: 1 });
- wrapper.update();
+ const { getByRole, rerender } = render();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('zero');
- expect(wrapper.find('input').props().value).toEqual('one');
- });
+ rerender();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('one');
});
it('changes to a selected item on key change', () => {
@@ -205,232 +158,214 @@ describe('ComboBox', () => {
{ key: 0, text: 'zero' },
{ key: 1, text: 'one' },
];
- safeMount(, wrapper => {
- expect(wrapper.find('input').props().value).toEqual('zero');
-
- wrapper.setProps({ selectedKey: null });
- wrapper.update();
+ const { getByRole, rerender } = render();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('zero');
- expect(wrapper.find('input').props().value).toEqual('');
- });
+ rerender();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('');
});
it('Applies correct attributes to the selected option', () => {
- safeMount(, wrapper => {
- // open combobox to check options list
- wrapper.find('button').simulate('click');
+ const { getByRole, getAllByRole } = render();
- const options = wrapper.find(BUTTON_OPTION);
- expect(options.at(1).prop('aria-selected')).toEqual('true');
- });
+ const combobox = getByRole('combobox');
+ // open combobox to select one option
+ userEvent.click(combobox);
+ userEvent.click(getAllByRole('option')[0], undefined, { skipPointerEventsCheck: true });
+ // reopen combobox to check selected option
+ userEvent.click(combobox);
+ expect(getAllByRole('option')[0].getAttribute('aria-selected')).toEqual('true');
});
it('Renders a placeholder', () => {
const placeholder = 'Select an option';
- safeCreate(, container => {
- const inputElement = container.root.findByType('input');
- expect(inputElement.props.placeholder).toEqual(placeholder);
- expect(inputElement.props.value).toEqual('');
- });
+ const { getByRole } = render();
+
+ const combobox = getByRole('combobox');
+ expect(combobox.getAttribute('placeholder')).toEqual(placeholder);
+ expect(combobox.getAttribute('value')).toEqual('');
});
it('Does not automatically add new options when allowFreeform is on in controlled case', () => {
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('input', { target: { value: 'f' } });
- inputElement.simulate('keydown', { which: KeyCodes.enter });
+ const { getByRole, getAllByRole } = render(
+ ,
+ );
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f{enter}');
- // open combobox to check options list
- wrapper.find('button').simulate('click');
+ const caretdownButton = getByRole('presentation', { hidden: true });
+ userEvent.click(caretdownButton);
- expect(wrapper.find(BUTTON_OPTION)).toHaveLength(DEFAULT_OPTIONS.length);
- });
+ expect(getAllByRole('option')).toHaveLength(DEFAULT_OPTIONS.length);
});
it('Automatically adds new options when allowFreeform is on in uncontrolled case', () => {
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('input', { target: { value: 'f' } });
- inputElement.simulate('keydown', { which: KeyCodes.enter });
+ const { getByRole, getAllByRole } = render();
- // open combobox to check options list
- wrapper.find('button').simulate('click');
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f{enter}');
- const options = wrapper.find(BUTTON_OPTION);
- expect(options.at(options.length - 1).text()).toEqual('f');
- });
+ const caretdownButton = getByRole('presentation', { hidden: true });
+ userEvent.click(caretdownButton);
+
+ const options = getAllByRole('option');
+ expect(options[options.length - 1].textContent).toEqual('f');
});
it('Renders a default value with options', () => {
- safeCreate(, container => {
- const inputElement = container.root.findByType('input');
- expect(inputElement.props.value).toEqual('1');
- });
+ const { getByRole } = render();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('1');
});
it('Renders a default value with no options', () => {
- safeCreate(, container => {
- const inputElement = container.root.findByType('input');
- expect(inputElement.props.value).toEqual('1');
- });
+ const { getByRole } = render();
+ expect(getByRole('combobox').getAttribute('value')).toEqual('1');
});
it('Can change items in uncontrolled case', () => {
- safeMount(, wrapper => {
- // open the menu and click the second item
- wrapper.find('button').simulate('click');
- const option = wrapper.find(BUTTON_OPTION).at(1);
- option.simulate('click');
+ const { getByRole, getAllByRole } = render();
+
+ // open the menu and click the second item
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
+ const selectedOption = getAllByRole('option')[1];
+ userEvent.click(selectedOption, undefined, { skipPointerEventsCheck: true });
- // check item is selected
- expect(wrapper.find('input').props().value).toBe('2');
- });
+ // check item is selected
+ expect(combobox.getAttribute('value')).toEqual('2');
});
it('Does not automatically change items in controlled case', () => {
- safeMount(, wrapper => {
- // open the menu and click the second item
- wrapper.find('button').simulate('click');
- const option = wrapper.find(BUTTON_OPTION).at(1);
- option.simulate('click');
+ const { getByRole, getAllByRole } = render();
+
+ // open the menu and click the second item
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
+ const selectedOption = getAllByRole('option')[1];
+ userEvent.click(selectedOption, undefined, { skipPointerEventsCheck: true });
- // check item is not selected since combobox is controlled
- expect(wrapper.find('input').props().value).toBe('1');
- });
+ // check item is not selected since combobox is controlled
+ expect(combobox.getAttribute('value')).toEqual('1');
});
it('Multiselect does not mutate props', () => {
- safeMount(, wrapper => {
- // open combobox
- wrapper.find('button').simulate('click');
+ const { getByRole, getAllByRole } = render(
+ ,
+ );
+
+ // open combobox
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- // select second option
- let dropdownOption = wrapper.find(CHECKBOX_OPTION).at(1);
- expect(dropdownOption.props().checked).toBeFalsy(); // ensure it's not already selected
- dropdownOption.simulate('change');
- wrapper.update();
+ // select second option
+ const secondOption = getAllByRole('option')[1];
+ expect(secondOption.getAttribute('aria-selected')).toEqual('false'); // ensure it's not already selected
+ userEvent.click(secondOption, undefined, { skipPointerEventsCheck: true });
- // checkbox selected
- dropdownOption = wrapper.find(CHECKBOX_OPTION).at(1);
- expect(dropdownOption.props().checked).toBeTruthy();
- // option object not mutated
- expect(!!DEFAULT_OPTIONS[1].selected).toBeFalsy();
- });
+ // checkbox selected
+ expect(secondOption.getAttribute('aria-selected')).toEqual('true');
+ // option object not mutated
+ expect(!!DEFAULT_OPTIONS[1].selected).toBeFalsy();
});
it('Can insert text in uncontrolled case with autoComplete and allowFreeform on', () => {
- safeMount(
+ const { getByRole } = render(
,
- wrapper => {
- wrapper.find('input').simulate('input', { target: { value: 'f' } });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('Foo');
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f');
+ expect(combobox.getAttribute('value')).toEqual('Foo');
});
it('Can insert text in uncontrolled case with autoComplete on and allowFreeform off', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('input', { target: { value: 'f' } });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('Foo');
- });
+ const { getByRole } = render();
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f');
+ expect(combobox.getAttribute('value')).toEqual('Foo');
});
it('Can insert non latin text in uncontrolled case with autoComplete on and allowFreeform off', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('input', { target: { value: 'п' } });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('папа');
- });
+ const { getByRole } = render();
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'п');
+ expect(combobox.getAttribute('value')).toEqual('папа');
});
it('Can insert text in uncontrolled case with autoComplete off and allowFreeform on', () => {
- safeMount(
+ const { getByRole } = render(
,
- wrapper => {
- wrapper.find('input').simulate('input', { target: { value: 'f' } });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('f');
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f');
+ expect(combobox.getAttribute('value')).toEqual('f');
});
it('Can insert text in uncontrolled case with autoComplete and allowFreeform off', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('keydown', { which: 'f' });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('One');
- });
+ const { getByRole } = render();
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f');
+ expect(combobox.getAttribute('value')).toEqual('One');
});
it('Can insert an empty string in uncontrolled case with autoComplete and allowFreeform on', () => {
- safeMount(
+ const { getByRole } = render(
,
- wrapper => {
- // Have to manually update the input element beforehand due to issues with Autofill in enzyme
- const input = wrapper.find('input');
- (input.getDOMNode() as HTMLInputElement).value = '';
- input.simulate('input', { target: { value: '' } });
- input.simulate('keydown', { which: KeyCodes.enter });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('');
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.clear(combobox);
+ userEvent.type(combobox, '{enter}');
+ expect(combobox.getAttribute('value')).toEqual('');
});
it('Cannot insert an empty string in uncontrolled case with autoComplete on and allowFreeform off', () => {
- safeMount(, wrapper => {
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: '' } });
- input.simulate('keydown', { which: KeyCodes.enter });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('One');
- });
+ const { getByRole } = render();
+
+ const combobox = getByRole('combobox');
+ userEvent.clear(combobox);
+ userEvent.type(combobox, '{enter}');
+ expect(combobox.getAttribute('value')).toEqual('One');
});
it('Can insert an empty string in uncontrolled case with autoComplete off and allowFreeform on', () => {
- safeMount(
+ const { getByRole } = render(
,
- wrapper => {
- // Have to manually update the input element beforehand due to issues with Autofill in enzyme
- const input = wrapper.find('input');
- (input.getDOMNode() as HTMLInputElement).value = '';
- input.simulate('input', { target: { value: '' } });
- input.simulate('keydown', { which: KeyCodes.enter });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('');
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.clear(combobox);
+ userEvent.type(combobox, '{enter}');
+ expect(combobox.getAttribute('value')).toEqual('');
});
it('Cannot insert an empty string in uncontrolled case with autoComplete and allowFreeform off', () => {
- safeMount(, wrapper => {
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: '' } });
- input.simulate('keydown', { which: KeyCodes.enter });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('One');
- });
+ const { getByRole } = render();
+
+ const combobox = getByRole('combobox');
+ userEvent.clear(combobox);
+ userEvent.type(combobox, '{enter}');
+ expect(combobox.getAttribute('value')).toEqual('One');
});
it(
'Can insert an empty string after removing a pending value in uncontrolled case ' +
'with autoComplete and allowFreeform on',
() => {
- safeMount(
+ const { getByRole } = render(
,
- wrapper => {
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: 'f' } });
- // Have to manually update the input element beforehand due to issues with Autofill in enzyme
- (input.getDOMNode() as HTMLInputElement).value = '';
- input.simulate('input', { target: { value: '' } });
- input.simulate('keydown', { which: KeyCodes.enter });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('');
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f');
+ userEvent.clear(combobox);
+ userEvent.type(combobox, '{enter}');
+ expect(combobox.getAttribute('value')).toEqual('');
},
);
@@ -438,14 +373,13 @@ describe('ComboBox', () => {
'Cannot insert an empty string after removing a pending value in uncontrolled case ' +
'with autoComplete on and allowFreeform off',
() => {
- safeMount(, wrapper => {
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: 'f' } });
- input.simulate('input', { target: { value: '' } });
- input.simulate('keydown', { which: KeyCodes.enter });
- wrapper.update();
- expect(wrapper.find('input').props().value).toBe('Foo');
- });
+ const { getByRole } = render();
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f');
+ userEvent.clear(combobox);
+ userEvent.type(combobox, '{enter}');
+ expect(combobox.getAttribute('value')).toEqual('Foo');
},
);
@@ -453,19 +387,15 @@ describe('ComboBox', () => {
'Can insert an empty string after removing a pending value in uncontrolled case ' +
'with autoComplete off and allowFreeform on',
() => {
- safeMount(
+ const { getByRole } = render(
,
- wrapper => {
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: 'f' } });
- // Have to manually update the input element beforehand due to issues with Autofill in enzyme
- (input.getDOMNode() as HTMLInputElement).value = '';
- input.simulate('input', { target: { value: '' } });
- input.simulate('keydown', { which: KeyCodes.enter });
- wrapper.update();
- expect(wrapper.find('input').props().value).toEqual('');
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f');
+ userEvent.clear(combobox);
+ userEvent.type(combobox, '{enter}');
+ expect(combobox.getAttribute('value')).toEqual('');
},
);
@@ -473,43 +403,42 @@ describe('ComboBox', () => {
'Cannot insert an empty string after removing a pending value in uncontrolled case ' +
'with autoComplete and allowFreeform off',
() => {
- safeMount(, wrapper => {
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: 'f' } });
- input.simulate('input', { target: { value: '' } });
- input.simulate('keydown', { which: KeyCodes.enter });
- wrapper.update();
- expect(wrapper.find('input').props().value).toEqual('One');
- });
+ const { getByRole } = render();
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f');
+ userEvent.clear(combobox);
+ userEvent.type(combobox, '{enter}');
+ expect(combobox.getAttribute('value')).toEqual('One');
},
);
it('Can change selected option with keyboard', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('keydown', { which: KeyCodes.down });
- expect(wrapper.find('input').props().value).toEqual('Foo');
- });
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, '{arrowdown}');
+ expect(combobox.getAttribute('value')).toEqual('Foo');
});
it('Can change selected option with keyboard, looping from top to bottom', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('keydown', { which: KeyCodes.up });
- expect(wrapper.find('input').props().value).toEqual('Bar');
- });
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, '{arrowup}');
+ expect(combobox.getAttribute('value')).toEqual('Bar');
});
it('Can change selected option with keyboard, looping from bottom to top', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('keydown', { which: KeyCodes.down });
- expect(wrapper.find('input').props().value).toEqual('One');
- });
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, '{arrowdown}');
+ expect(combobox.getAttribute('value')).toEqual('One');
});
it('Can change selected option with keyboard, looping from top to bottom', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('keydown', { which: KeyCodes.up });
- expect(wrapper.find('input').props().value).toEqual('Bar');
- });
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, '{arrowup}');
+ expect(combobox.getAttribute('value')).toEqual('Bar');
});
it('Changing selected option with keyboard triggers onChange with the correct value', () => {
@@ -517,8 +446,8 @@ describe('ComboBox', () => {
void,
[React.FormEvent, IComboBoxOption | undefined, number | undefined, string | undefined]
>();
- render();
-
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
expect(onChange).not.toHaveBeenCalled();
userEvent.tab();
@@ -530,86 +459,80 @@ describe('ComboBox', () => {
expect(onChange.mock.calls[0][2]).toEqual(2);
expect(onChange.mock.calls[0][3]).toEqual(DEFAULT_OPTIONS3[2].text);
- safeMount(, wrapper => {
- wrapper.find('input').simulate('keydown', { which: KeyCodes.up });
- expect(wrapper.find('input').props().value).toEqual('Bar');
- });
+ userEvent.type(combobox, '{arrowup}');
+ expect(combobox.getAttribute('value')).toEqual('One');
});
it('Cannot insert text while disabled', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('keydown', { which: KeyCodes.a });
- expect(wrapper.find('input').props().value).toEqual('One');
- });
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'a');
+ expect(combobox.getAttribute('value')).toEqual('One');
});
it('Cannot change selected option with keyboard while disabled', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('keydown', { which: KeyCodes.down });
- expect(wrapper.find('input').props().value).toEqual('One');
- });
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, '{arrowdown}');
+ expect(combobox.getAttribute('value')).toEqual('One');
});
it('Cannot expand the menu when clicking on the input while disabled', () => {
- safeMount(, wrapper => {
- wrapper.find('input').simulate('click');
- expect(wrapper.find(OPEN_SELECTOR).length).toEqual(0);
- });
+ const { getByRole, queryAllByRole } = render();
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
+ expect(queryAllByRole('option')).toHaveLength(0);
});
it('Cannot expand the menu when clicking on the button while disabled', () => {
- safeMount(, wrapper => {
- wrapper.find('button').simulate('click');
- expect(wrapper.find(OPEN_SELECTOR).length).toEqual(0);
- });
+ const { getByRole, queryAllByRole } = render(
+ ,
+ );
+ const caretdownButton = getByRole('presentation', { hidden: true });
+ userEvent.click(caretdownButton);
+ expect(queryAllByRole('option')).toHaveLength(0);
});
it('Cannot expand the menu when focused with a button while combobox is disabled', () => {
const comboBoxRef = React.createRef();
- safeMount(
+ const { queryAllByRole } = render(
,
- wrapper => {
- comboBoxRef.current?.focus(true);
- expect(comboBoxRef.current.state.isOpen).toEqual(false);
- },
);
+ comboBoxRef.current?.focus(true);
+ expect(queryAllByRole('option')).toHaveLength(0);
});
it('Calls onMenuOpen when clicking on the button', () => {
const onMenuOpenMock = jest.fn();
- safeMount(, wrapper => {
- wrapper.find('button').simulate('click');
- expect(onMenuOpenMock.mock.calls.length).toBe(1);
- });
+ const { getByRole, queryAllByRole } = render(
+ ,
+ );
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
+ expect(queryAllByRole('options')).toBeTruthy;
});
it('Opens on focus when openOnKeyboardFocus is true', () => {
const onMenuOpenMock = jest.fn();
- safeMount(
+ const { queryAllByRole } = render(
,
- wrapper => {
- const input = wrapper.find('input');
- input.simulate('focus');
- input.simulate('keyup');
- expect(onMenuOpenMock.mock.calls.length).toBe(1);
- },
);
+ userEvent.tab();
+ expect(queryAllByRole('options')).toBeTruthy;
});
it('Calls onMenuOpen when touch start on the input', () => {
- safeMount(
- ,
- wrapper => {
- const input = wrapper.find('input');
-
- // in a normal scenario, when we do a touchstart we would also cause a click event to fire.
- // This doesn't happen in the simulator so we're manually adding this in.
- input.simulate('touchstart');
- input.simulate('click');
-
- expect(wrapper.find(OPEN_SELECTOR).length).toEqual(1);
- },
+ const onMenuOpenMock = jest.fn();
+ const { getByRole, queryAllByRole } = render(
+ ,
);
+
+ // in a normal scenario, when we do a touchstart we would also cause a click event to fire.
+ // This doesn't happen in the simulator so we're manually adding this in.
+ const combobox = getByRole('combobox');
+ fireEvent.touchStart(combobox);
+ userEvent.click(combobox);
+ expect(queryAllByRole('options')).toBeTruthy;
});
it('onPendingValueChanged triggers for all indexes', () => {
@@ -619,22 +542,19 @@ describe('ComboBox', () => {
indexSeen.push(index);
}
};
- safeMount(
+
+ const { getByRole } = render(
,
- wrapper => {
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: 'f' } });
- input.simulate('keydown', { which: KeyCodes.down });
- input.simulate('keydown', { which: KeyCodes.up });
- expect(indexSeen).toContain(0);
- expect(indexSeen).toContain(1);
- },
);
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'f{arrowdown}{arrowup}');
+ expect(indexSeen).toContain(0);
+ expect(indexSeen).toContain(1);
});
it('onPendingValueChanged is called with an empty string when the input is cleared', () => {
@@ -643,20 +563,13 @@ describe('ComboBox', () => {
changedValue = value;
};
- safeMount(
+ const { getByRole } = render(
,
- wrapper => {
- // Simulate typing one character into the ComboBox input
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: 'a' } });
-
- // Simulate clearing the ComboBox input
- // (have to manually update the input element beforehand due to issues with Autofill in enzyme)
- (input.getDOMNode() as HTMLInputElement).value = '';
- input.simulate('input', { target: { value: '' } });
- expect(changedValue).toEqual('');
- },
);
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'a');
+ userEvent.clear(combobox);
+ expect(changedValue).toEqual('');
});
it('onInputValueChange is called whenever the input changes', () => {
@@ -665,34 +578,25 @@ describe('ComboBox', () => {
changedValue = value;
};
- safeMount(
+ const { getByRole } = render(
,
- wrapper => {
- // Simulate typing one character into the ComboBox input
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: 'a' } });
- expect(changedValue).toEqual('a');
-
- // Simulate clearing the ComboBox input
- // (have to manually update the input element beforehand due to issues with Autofill in enzyme)
- (input.getDOMNode() as HTMLInputElement).value = '';
- input.simulate('input', { target: { value: '' } });
- expect(changedValue).toEqual('');
- },
);
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'a');
+ expect(changedValue).toEqual('a');
+
+ userEvent.clear(combobox);
+ expect(changedValue).toEqual('');
});
it('suggestedDisplayValue is set to undefined when the selected input is cleared', () => {
- safeMount(, wrapper => {
- expect(wrapper.find('input').props().value).toEqual('1');
+ const { getByRole, rerender } = render();
- wrapper.setProps({ selectedKey: null });
- wrapper.update();
- expect(wrapper.find('input').props().value).toEqual('');
+ const combobox = getByRole('combobox');
+ expect(combobox.getAttribute('value')).toEqual('1');
- const autofill = wrapper.find(Autofill);
- expect(autofill.props().suggestedDisplayValue).toEqual(undefined);
- });
+ rerender();
+ expect(combobox.getAttribute('value')).toEqual('');
});
it('Can type a complete option with autocomplete and allowFreeform on and submit it', () => {
@@ -702,40 +606,37 @@ describe('ComboBox', () => {
>();
const initialOption = { key: '1', text: 'Text' };
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('input', { target: { value: 't' } });
- inputElement.simulate('input', { target: { value: 'te' } });
- inputElement.simulate('input', { target: { value: 'tex' } });
- inputElement.simulate('input', { target: { value: 'text' } });
- inputElement.simulate('keydown', { which: KeyCodes.enter });
- expect(onChange).toHaveBeenCalledTimes(1);
- expect(onChange.mock.calls[0][1]).toEqual(initialOption);
- expect(onChange.mock.calls[0][2]).toEqual(0);
- expect(onChange.mock.calls[0][3]).toEqual(initialOption.text);
+ const { getByRole } = render(
+ ,
+ );
- wrapper.update();
- expect(wrapper.find('input').props().value).toEqual('Text');
- });
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'text{enter}');
+ expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange.mock.calls[0][1]).toEqual(initialOption);
+ expect(onChange.mock.calls[0][2]).toEqual(0);
+ expect(onChange.mock.calls[0][3]).toEqual(initialOption.text);
+ expect(combobox.getAttribute('value')).toEqual('Text');
});
it('merges callout classNames', () => {
- safeMount(
+ const { baseElement, getByRole } = render(
,
- wrapper => {
- wrapper.find('button').simulate('click');
-
- const callout = wrapper.find('.ms-Callout').getDOMNode();
- expect(callout).toBeTruthy();
- expect(callout.classList.contains('ms-ComboBox-callout')).toBeTruthy();
- expect(callout.classList.contains('foo')).toBeTruthy();
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
+
+ const callout = baseElement.querySelector('.ms-Callout');
+ expect(callout).toBeTruthy();
+ expect(callout!.classList.contains('ms-ComboBox-callout')).toBeTruthy();
+ expect(callout!.classList.contains('foo')).toBeTruthy();
});
it('Can clear text in controlled case with autoComplete off and allowFreeform on', () => {
let updatedText: string | undefined;
- safeMount(
+
+ const { getByRole } = render(
{
updatedText = value;
}}
/>,
- wrapper => {
- const input = wrapper.find('input');
- // Have to manually update the input element beforehand due to issues with Autofill in enzyme
- (input.getDOMNode() as HTMLInputElement).value = '';
- input.simulate('input', { target: { value: '' } });
- input.simulate('keydown', { which: KeyCodes.enter });
- wrapper.update();
-
- expect(updatedText).toEqual('');
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.clear(combobox);
+ userEvent.type(combobox, '{enter}');
+ expect(updatedText).toEqual('');
});
it('Can clear text in controlled case with autoComplete off and allowFreeform on', () => {
let updatedText: string | undefined;
- safeMount(
+
+ const { getByRole } = render(
{
updatedText = value;
}}
/>,
- wrapper => {
- const input = wrapper.find('input');
- input.simulate('input', { target: { value: 'ab' } });
- input.simulate('keydown', { which: KeyCodes.backspace });
- input.simulate('input', { target: { value: 'a' } });
- input.simulate('keydown', { which: KeyCodes.backspace });
- wrapper.update();
-
- // Have to manually update the input element beforehand due to issues with Autofill in enzyme
- (input.getDOMNode() as HTMLInputElement).value = '';
- input.simulate('input', { target: { value: '' } });
- wrapper.update();
- expect((input.getDOMNode() as HTMLInputElement).value).toEqual('');
- input.simulate('keydown', { which: KeyCodes.enter });
-
- expect(updatedText).toEqual('');
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, 'ab{backspace}a{backspace}');
+ userEvent.clear(combobox);
+ expect(combobox.getAttribute('value')).toEqual('');
+
+ userEvent.type(combobox, '{enter}');
+ expect(updatedText).toEqual('');
});
it('in multiSelect mode, selectedOptions are correct after performing multiple selections using mouse click', () => {
const comboBoxRef = React.createRef();
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
+ const { getByRole, getAllByRole } = render(
+ ,
+ );
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(0).simulate('change');
- options.at(1).simulate('change');
- options.at(2).simulate('change');
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, '{enter}');
- expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['1', '2', '3']);
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(options[1], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(options[2], undefined, { skipPointerEventsCheck: true });
+ expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['1', '2', '3']);
});
it('in multiSelect mode, defaultSelectedKey produces correct display input', () => {
const comboBoxRef = React.createRef();
const keys = [DEFAULT_OPTIONS[0].key as string, DEFAULT_OPTIONS[2].key as string];
- safeMount(
+ const { getByRole, getAllByRole } = render(
,
- wrapper => {
- const inputElement = wrapper.find('input');
- expect(inputElement.props().value).toEqual(keys.join(', '));
+ );
- inputElement.simulate('keydown', { which: KeyCodes.enter });
+ const combobox = getByRole('combobox');
+ expect(combobox.getAttribute('value')).toEqual(keys.join(', '));
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(2).simulate('change');
- options.at(0).simulate('change');
- wrapper.update();
+ userEvent.click(combobox);
- expect((inputElement.getDOMNode() as HTMLInputElement).value).toEqual('');
- },
- );
+ const options = getAllByRole('option');
+ userEvent.click(options[2], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ expect(combobox.getAttribute('value')).toEqual('');
});
it('in multiSelect mode, input has correct value after selecting options', () => {
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(0).simulate('change');
- options.at(2).simulate('change');
+ const { container, getByRole, getAllByRole } = render();
+
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- const keys = [DEFAULT_OPTIONS[0].key, DEFAULT_OPTIONS[2].key];
- expect((inputElement.getDOMNode() as HTMLInputElement).value).toEqual(keys.join(', '));
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(options[2], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(combobox);
+ userEvent.click(container);
+
+ const keys = [DEFAULT_OPTIONS[0].key, DEFAULT_OPTIONS[2].key];
+ expect(combobox.getAttribute('value')).toEqual(keys.join(', '));
});
it('in multiSelect mode, input has correct value when multiSelectDelimiter specified', () => {
const delimiter = '; ';
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(0).simulate('change');
- options.at(2).simulate('change');
+ const { container, getByRole, getAllByRole } = render(
+ ,
+ );
- const keys = [DEFAULT_OPTIONS[0].key, DEFAULT_OPTIONS[2].key];
- expect((inputElement.getDOMNode() as HTMLInputElement).value).toEqual(keys.join(delimiter));
- });
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
+
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(options[2], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(combobox);
+ userEvent.click(container);
+ const keys = [DEFAULT_OPTIONS[0].key, DEFAULT_OPTIONS[2].key];
+ expect(combobox.getAttribute('value')).toEqual(keys.join(delimiter));
});
it('in multiSelect mode, optional onItemClick callback invoked per option select', () => {
const onItemClickMock = jest.fn();
- safeMount(, wrapper => {
- wrapper.find('input').simulate('keydown', { which: KeyCodes.enter });
+ const { getByRole, getAllByRole } = render(
+ ,
+ );
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(0).simulate('change');
- options.at(1).simulate('change');
- options.at(2).simulate('change');
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- expect(onItemClickMock).toHaveBeenCalledTimes(3);
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(options[1], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(options[2], undefined, { skipPointerEventsCheck: true });
+ expect(onItemClickMock).toHaveBeenCalledTimes(3);
});
it('in multiSelect mode, selectAll selects all options', () => {
@@ -872,17 +767,19 @@ describe('ComboBox', () => {
{ key: 'selectAll', text: 'Select All', itemType: SelectableOptionMenuItemType.SelectAll },
...DEFAULT_OPTIONS,
];
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
+ const { container, getByRole, getAllByRole } = render(
+ ,
+ );
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(0).simulate('change');
- inputElement.simulate('keydown', { which: KeyCodes.escape });
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['selectAll', '1', '2', '3']);
- expect(wrapper.find('input').props().value).toEqual('1, 2, 3');
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ userEvent.type(combobox, '{esc}');
+ userEvent.click(container);
+ expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['selectAll', '1', '2', '3']);
+ expect(combobox.getAttribute('value')).toEqual('1, 2, 3');
});
it('in multiSelect mode, selectAll does not select disabled options', () => {
@@ -892,15 +789,17 @@ describe('ComboBox', () => {
...DEFAULT_OPTIONS,
];
SELECTALL_OPTIONS[1] = { ...SELECTALL_OPTIONS[1], disabled: true };
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(0).simulate('change');
+ const { getByRole, getAllByRole } = render(
+ ,
+ );
+
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['selectAll', '2', '3']);
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['selectAll', '2', '3']);
});
it('in multiSelect mode, selectAll does not select heeaders or dividers', () => {
@@ -909,15 +808,16 @@ describe('ComboBox', () => {
{ key: 'selectAll', text: 'Select All', itemType: SelectableOptionMenuItemType.SelectAll },
...RENDER_OPTIONS,
];
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
+ const { getByRole, getAllByRole } = render(
+ ,
+ );
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(0).simulate('change');
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['selectAll', '1', '2']);
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['selectAll', '1', '2']);
});
it('in multiSelect mode, selectAll checked calculation ignores headers, dividers, and disabled options', () => {
@@ -927,15 +827,16 @@ describe('ComboBox', () => {
...RENDER_OPTIONS,
];
SELECTALL_OPTIONS[2] = { ...SELECTALL_OPTIONS[2], disabled: true };
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
+ const { getByRole, getAllByRole } = render(
+ ,
+ );
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(2).simulate('change');
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['2', 'selectAll']);
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[2], undefined, { skipPointerEventsCheck: true });
+ expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['2', 'selectAll']);
});
it('in multiSelect mode, modifying option selection updates selectAll', () => {
@@ -944,21 +845,22 @@ describe('ComboBox', () => {
{ key: 'selectAll', text: 'Select All', itemType: SelectableOptionMenuItemType.SelectAll },
...DEFAULT_OPTIONS,
];
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(0).simulate('change');
- // un-check one option
- options.at(1).simulate('change');
+ const { getByRole, getAllByRole } = render(
+ ,
+ );
- expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['2', '3']);
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- // re-check option
- options.at(1).simulate('change');
- expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['2', '3', '1', 'selectAll']);
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ // un-check one option
+ userEvent.click(options[1], undefined, { skipPointerEventsCheck: true });
+ expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['2', '3']);
+ // re-check option
+ userEvent.click(options[1], undefined, { skipPointerEventsCheck: true });
+ expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['2', '3', '1', 'selectAll']);
});
it('in multiSelect mode with mixed selected, selectAll is indeterminate', () => {
@@ -967,16 +869,15 @@ describe('ComboBox', () => {
{ key: 'selectAll', text: 'Select All', itemType: SelectableOptionMenuItemType.SelectAll },
...DEFAULT_OPTIONS,
];
- safeMount(
+ const { getByRole, getAllByRole } = render(
,
- wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
-
- const options = wrapper.find(CHECKBOX_OPTION);
- expect(options.at(0).props()['aria-checked']).toEqual('mixed');
- },
);
+
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
+
+ const options = getAllByRole('option');
+ expect(options[0].getAttribute('aria-checked')).toEqual('mixed');
});
it('in multiSelect mode, checking options sets selectAll to indeterminate', () => {
@@ -985,23 +886,22 @@ describe('ComboBox', () => {
{ key: 'selectAll', text: 'Select All', itemType: SelectableOptionMenuItemType.SelectAll },
...DEFAULT_OPTIONS,
];
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(1).simulate('change');
+ const { getByRole, getAllByRole } = render(
+ ,
+ );
+
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- let selectAll = wrapper.find(CHECKBOX_OPTION).at(0);
- expect(selectAll.props()['aria-checked']).toEqual('mixed');
+ const options = getAllByRole('option');
+ userEvent.click(options[1], undefined, { skipPointerEventsCheck: true });
+ expect(options[0].getAttribute('aria-checked')).toEqual('mixed');
- options.at(2).simulate('change');
- options.at(3).simulate('change');
+ userEvent.click(options[2], undefined, { skipPointerEventsCheck: true });
+ userEvent.click(options[3], undefined, { skipPointerEventsCheck: true });
- selectAll = wrapper.find(CHECKBOX_OPTION).at(0);
- expect(selectAll.props().checked).toEqual(true);
- expect(selectAll.props()['aria-checked']).toBeUndefined();
- });
+ expect(options[0].getAttribute('aria-checked')).toEqual('mixed');
});
it('in multiSelect mode, checking an indeterminate selectAll checks all options', () => {
@@ -1010,18 +910,16 @@ describe('ComboBox', () => {
{ key: 'selectAll', text: 'Select All', itemType: SelectableOptionMenuItemType.SelectAll },
...DEFAULT_OPTIONS,
];
- safeMount(
+ const { getByRole, getAllByRole } = render(
,
- wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
+ );
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(0).simulate('change');
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['selectAll', '1', '2', '3']);
- },
- );
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ expect(comboBoxRef.current!.selectedOptions.map(o => o.key)).toEqual(['selectAll', '1', '2', '3']);
});
it('in single-select mode, selectAll behaves as a normal option', () => {
@@ -1030,90 +928,89 @@ describe('ComboBox', () => {
{ key: 'selectAll', text: 'Select All', itemType: SelectableOptionMenuItemType.SelectAll },
...RENDER_OPTIONS,
];
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- inputElement.simulate('keydown', { which: KeyCodes.enter });
- const options = wrapper.find(BUTTON_OPTION);
- options.at(0).simulate('click');
+ const { getByRole, getAllByRole } = render();
+
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- expect(wrapper.find('input').props().value).toEqual('Select All');
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ expect(combobox.getAttribute('value')).toEqual('Select All');
});
it('invokes optional onItemClick callback on option select', () => {
const onItemClickMock = jest.fn();
- safeMount(, wrapper => {
- wrapper.find('button').simulate('click');
+ const { getByRole, getAllByRole } = render();
- const option = wrapper.find(BUTTON_OPTION).at(0);
- option.simulate('click');
+ const combobox = getByRole('combobox');
+ userEvent.click(combobox);
- expect(onItemClickMock).toHaveBeenCalledTimes(1);
- });
+ const options = getAllByRole('option');
+ userEvent.click(options[0], undefined, { skipPointerEventsCheck: true });
+ expect(onItemClickMock).toHaveBeenCalledTimes(1);
});
it('defaults to ariaDescribedBy prop when passing id to input', () => {
const ariaId = 'customAriaDescriptionId';
- safeMount(
+ const { getByRole } = render(
,
- wrapper => {
- const inputElement = wrapper.find('input').getDOMNode();
- expect(inputElement.getAttribute('aria-describedby')).toBe(ariaId);
- },
);
+
+ const combobox = getByRole('combobox');
+ expect(combobox.getAttribute('aria-describedby')).toBe(ariaId);
});
it('allows adding a custom aria-describedby id to the input via an attribute', () => {
const ariaId = 'customAriaDescriptionId';
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input').getDOMNode();
- expect(inputElement.getAttribute('aria-describedby')).toBe(ariaId);
- });
+ const { getByRole } = render(
+ ,
+ );
+
+ const combobox = getByRole('combobox');
+ expect(combobox.getAttribute('aria-describedby')).toBe(ariaId);
});
it('correctly handles (aria-labelledby) when label is also provided', () => {
const customId = 'customAriaLabelledById';
- safeMount(, wrapper => {
- const labelElement = wrapper.find('label').getDOMNode();
- const labelId = labelElement.getAttribute('id');
+ const { container, getByRole } = render(
+ ,
+ );
- const inputElement = wrapper.find('input').getDOMNode();
- expect(inputElement.getAttribute('aria-labelledby')).toBe(customId + ' ' + labelId);
- });
+ const combobox = getByRole('combobox');
+ const labelElement = container.querySelector('.ms-Label');
+ const labelId = labelElement!.getAttribute('id');
+ expect(combobox.getAttribute('aria-labelledby')).toBe(customId + ' ' + labelId);
});
it('sets ariaLabel on both the input and the dropdown list', () => {
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input').getDOMNode();
- expect(inputElement.getAttribute('aria-label')).toBe('customAriaLabel');
- expect(inputElement.getAttribute('aria-labelledby')).toBeNull();
-
- const listElement = wrapper.find('.ms-ComboBox-optionsContainer').getDOMNode();
- expect(listElement.getAttribute('aria-label')).toBe('customAriaLabel');
- expect(listElement.getAttribute('aria-labelledby')).toBeNull();
- });
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
+ expect(combobox.getAttribute('aria-label')).toBe('customAriaLabel');
+ expect(combobox.getAttribute('aria-labelledby')).toBeNull();
+ userEvent.click(combobox);
+ const listElement = getByRole('listbox');
+ expect(listElement.getAttribute('aria-label')).toBe('customAriaLabel');
+ expect(listElement.getAttribute('aria-labelledby')).toBeNull();
});
it('adds aria-required to the DOM when the required prop is set to true', () => {
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input').getDOMNode();
- expect(inputElement.getAttribute('aria-required')).toEqual('true');
- });
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
+ expect(combobox.getAttribute('aria-required')).toEqual('true');
});
it('does not add aria-required to the DOM when the required prop is not set', () => {
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input').getDOMNode();
- expect(inputElement.getAttribute('aria-required')).toBeNull();
- });
+ const { getByRole } = render();
+ const combobox = getByRole('combobox');
+ expect(combobox.getAttribute('aria-required')).toBeNull();
});
it('with persistMenu, callout should exist before and after opening menu', () => {
const onMenuOpenMock = jest.fn();
const onMenuDismissedMock = jest.fn();
- safeMount(
+ const { baseElement, getByRole } = render(
{
onMenuOpen={onMenuOpenMock}
onMenuDismissed={onMenuDismissedMock}
/>,
- wrapper => {
- // Find menu
- const calloutBeforeOpen = wrapper.find('.ms-Callout').getDOMNode();
- expect(calloutBeforeOpen).toBeTruthy();
- expect(calloutBeforeOpen.classList.contains('ms-ComboBox-callout')).toBeTruthy();
-
- // Open combobox
- const buttonElement = wrapper.find('.ms-ComboBox button');
- buttonElement.simulate('click');
- expect(onMenuOpenMock.mock.calls.length).toBe(1);
-
- // Close combobox
- buttonElement.simulate('click');
- expect(onMenuDismissedMock.mock.calls.length).toBe(1);
-
- // Ensure menu is still there
- const calloutAfterClose = wrapper.find('.ms-Callout').getDOMNode();
- expect(calloutAfterClose).toBeTruthy();
- expect(calloutAfterClose.classList.contains('ms-ComboBox-callout')).toBeTruthy();
- },
);
+ const combobox = getByRole('combobox');
+
+ // Find menu
+ const calloutBeforeOpen = baseElement.querySelector('.ms-Callout');
+ expect(calloutBeforeOpen).toBeTruthy();
+ expect(calloutBeforeOpen!.classList.contains('ms-ComboBox-callout')).toBeTruthy();
+
+ userEvent.click(combobox);
+ expect(onMenuOpenMock.mock.calls.length).toBe(1);
+
+ userEvent.click(combobox);
+ expect(onMenuDismissedMock.mock.calls.length).toBe(1);
+
+ // Ensure menu is still there
+ const calloutAfterClose = baseElement.querySelector('.ms-Callout');
+ expect(calloutAfterClose).toBeTruthy();
+ expect(calloutAfterClose!.classList.contains('ms-ComboBox-callout')).toBeTruthy();
});
// Adds currentPendingValue to options and makes it selected onBlur
@@ -1152,19 +1046,15 @@ describe('ComboBox', () => {
text: 'ManuallyEnteredValue',
selected: true,
};
- safeMount(
- ,
- wrapper => {
- const inputElement = wrapper.find('input');
- _verifyStateVariables(wrapper, 'none', DEFAULT_OPTIONS, [0, 1, 2]);
- inputElement.simulate('focus');
- _verifyStateVariables(wrapper, 'focusing', DEFAULT_OPTIONS, [0, 1, 2]);
- inputElement.simulate('input', { target: { value: comboBoxOption.text } });
- _verifyStateVariables(wrapper, 'focusing', DEFAULT_OPTIONS, [0, 1, 2]);
- inputElement.simulate('blur');
- _verifyStateVariables(wrapper, 'none', [...DEFAULT_OPTIONS, comboBoxOption], [0, 1, 2, 3]);
- },
+ const selectedKeys = ['1', '2', '3'];
+ const { container, getByRole } = render(
+ ,
);
+ const combobox = getByRole('combobox');
+ userEvent.type(combobox, comboBoxOption.text);
+ //click on container to trigger onBlur
+ userEvent.click(container);
+ expect(combobox.getAttribute('value')).toEqual(selectedKeys.concat(comboBoxOption.text).join(', '));
});
// Adds currentPendingValue to options and makes it selected onBlur
@@ -1175,32 +1065,25 @@ describe('ComboBox', () => {
text: 'ManuallyEnteredValue',
selected: true,
};
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- _verifyStateVariables(wrapper, 'none', DEFAULT_OPTIONS, []);
- inputElement.simulate('focus');
- inputElement.simulate('keyup', { which: 10 });
- _verifyStateVariables(wrapper, 'focused', DEFAULT_OPTIONS, []);
- inputElement.simulate('input', { target: { value: comboBoxOption.text } });
- _verifyStateVariables(wrapper, 'focused', DEFAULT_OPTIONS, []);
- inputElement.simulate('blur');
- _verifyStateVariables(wrapper, 'none', [...DEFAULT_OPTIONS, comboBoxOption], [3]);
-
- inputElement.simulate('focus');
- _verifyStateVariables(wrapper, 'focusing', [...DEFAULT_OPTIONS, comboBoxOption], [3]);
- inputElement.simulate('input', { target: { value: comboBoxOption.text } });
- _verifyStateVariables(wrapper, 'focusing', [...DEFAULT_OPTIONS, comboBoxOption], [3]);
-
- // This should toggle the checkbox off. With multi-select the currentPendingValue is not reset on input change
- // because it would break keyboard accessibility
- wrapper.find('.ms-ComboBox button').simulate('click');
- const options = wrapper.find(CHECKBOX_OPTION);
- options.at(3).simulate('change');
-
- // with 'ManuallyEnteredValue' still in the input, on blur it should toggle the check back to on
- inputElement.simulate('blur');
- _verifyStateVariables(wrapper, 'none', [...DEFAULT_OPTIONS, { ...comboBoxOption, selected: true }], [3]);
- });
+
+ const { container, getByRole, getAllByRole } = render(
+ ,
+ );
+ const combobox = getByRole('combobox');
+ const caretdownButton = getByRole('presentation', { hidden: true });
+ userEvent.type(combobox, comboBoxOption.text);
+ //click on container to trigger onBlur
+ userEvent.click(container);
+
+ userEvent.type(combobox, comboBoxOption.text);
+ userEvent.click(caretdownButton);
+ const options = getAllByRole('option');
+ // This should toggle the checkbox off. With multi-select the currentPendingValue is not reset on input change
+ // because it would break keyboard accessibility
+ userEvent.click(options[3], undefined, { skipPointerEventsCheck: true });
+ // with 'ManuallyEnteredValue' still in the input, on blur it should toggle the check back to on
+ userEvent.click(container);
+ expect(combobox.getAttribute('value')).toEqual(comboBoxOption.text);
});
// adds currentPendingValue to options and makes it selected onBlur
@@ -1210,40 +1093,19 @@ describe('ComboBox', () => {
key: 'ManuallyEnteredValue',
text: 'ManuallyEnteredValue',
};
- safeMount(, wrapper => {
- const inputElement = wrapper.find('input');
- _verifyStateVariables(wrapper, 'none', DEFAULT_OPTIONS, []);
- inputElement.simulate('focus');
- _verifyStateVariables(wrapper, 'focusing', DEFAULT_OPTIONS, []);
- inputElement.simulate('input', { target: { value: comboBoxOption.text } });
- _verifyStateVariables(wrapper, 'focusing', DEFAULT_OPTIONS, []);
- inputElement.simulate('blur');
- _verifyStateVariables(wrapper, 'none', [...DEFAULT_OPTIONS, comboBoxOption], [3]);
-
- inputElement.simulate('focus');
- _verifyStateVariables(wrapper, 'focusing', [...DEFAULT_OPTIONS, comboBoxOption], [3]);
- wrapper.find('.ms-ComboBox button').simulate('click');
- const options = wrapper.find(BUTTON_OPTION);
- options.at(2).simulate('click');
-
- inputElement.simulate('blur');
- _verifyStateVariables(wrapper, 'none', [...DEFAULT_OPTIONS, comboBoxOption], [2]);
- });
- });
-
- function _verifyStateVariables(
- wrapper: ReactWrapper,
- focusState: 'none' | 'focused' | 'focusing',
- currentOptions: IComboBoxOption[],
- selectedIndices?: number[],
- ): void {
- // Once ComboBox is fully converted, we'll need to find another way to test this,
- // but for the time being we can use hacks to get these values from the internal class
- // (enzyme "selectors" support finding components by name)
- const comboBoxInternal = wrapper.find('ComboBoxInternal').instance() as any;
- expect(comboBoxInternal.state.focusState).toEqual(focusState);
- expect(comboBoxInternal.props.hoisted.currentOptions).toEqual(currentOptions);
- // This one could be tested using IComboBox.selectedOptions instead
- expect(comboBoxInternal.props.hoisted.selectedIndices).toEqual(selectedIndices);
- }
+
+ const { container, getByRole, getAllByRole } = render();
+ const combobox = getByRole('combobox');
+ const caretdownButton = getByRole('presentation', { hidden: true });
+ userEvent.type(combobox, comboBoxOption.text);
+ userEvent.click(container);
+ expect(combobox.getAttribute('value')).toEqual(comboBoxOption.text);
+
+ userEvent.click(caretdownButton);
+ const options = getAllByRole('option');
+ userEvent.click(options[2], undefined, { skipPointerEventsCheck: true });
+ //click on container to trigger onBlur
+ userEvent.click(container);
+ expect(combobox.getAttribute('value')).toEqual(DEFAULT_OPTIONS[2].text);
+ });
});
diff --git a/packages/react/src/components/ComboBox/__snapshots__/ComboBox.test.tsx.snap b/packages/react/src/components/ComboBox/__snapshots__/ComboBox.test.tsx.snap
index cf493e1160fcc..31f0e9bea56dc 100644
--- a/packages/react/src/components/ComboBox/__snapshots__/ComboBox.test.tsx.snap
+++ b/packages/react/src/components/ComboBox/__snapshots__/ComboBox.test.tsx.snap
@@ -1,832 +1,964 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ComboBox Renders correctly 1`] = `
-
+
-
-
+
`;
exports[`ComboBox Renders correctly when open 1`] = `
-
+
-
- * {
- left: 0px;
+ &:active {
position: relative;
- top: 0px;
}
- @media screen and (-ms-high-contrast: active), (forced-colors: active){& {
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:active {
-ms-high-contrast-adjust: none;
- background-color: Highlight;
- border-color: Highlight;
+ background-color: Window;
color: HighlightText;
forced-color-adjust: none;
}
- &:hover {
- background-color: #e1dfdd;
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:active:after {
+ border-color: Highlight;
+ }
+ &:focus {
+ border-color: #0078d4;
+ }
+ &:focus .ms-ComboBox-Input {
color: #201f1e;
}
- @media screen and (-ms-high-contrast: active), (forced-colors: active){&:hover {
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:focus .ms-ComboBox-Input {
-ms-high-contrast-adjust: none;
- background-color: Highlight;
- border-color: Highlight;
+ background-color: Window;
+ color: WindowText;
+ forced-color-adjust: none;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:focus {
+ -ms-high-contrast-adjust: none;
+ background-color: Window;
color: HighlightText;
forced-color-adjust: none;
}
- data-is-focusable="false"
- role="presentation"
- tabindex="-1"
- type="button"
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:focus:after {
+ border-color: Highlight;
+ }
+ &:focus:after {
+ border-radius: 2px;
+ border: 2px solid #0078d4;
+ bottom: 0px;
+ content: '';
+ left: 0px;
+ pointer-events: none;
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ }
+ data-ktp-target="true"
+ id="ComboBox0wrapper"
>
-
+ * {
+ left: 0px;
+ position: relative;
+ top: 0px;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){& {
+ -ms-high-contrast-adjust: none;
+ background-color: Highlight;
+ border-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
+ }
+ &:hover {
+ background-color: #e1dfdd;
+ color: #201f1e;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:hover {
+ -ms-high-contrast-adjust: none;
+ background-color: Highlight;
+ border-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
+ }
+ data-is-focusable="false"
+ role="presentation"
+ tabindex="-1"
+ type="button"
>
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
* {
+ left: 0px;
+ position: relative;
+ top: 0px;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){& {
+ border-color: Background;
+ border: none;
+ }
+ &.ms-Checkbox {
+ align-items: center;
+ display: flex;
+ }
+ &.ms-Button--command:hover:active {
+ background-color: #edebe9;
+ }
+ & .ms-Checkbox-label {
+ width: 100%;
+ }
+ &:hover {
+ background-color: #f3f2f1;
+ color: #201f1e;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:hover {
+ color: Highlight;
+ }
+ &:hover .ms-Button-icon {
+ color: #0078d4;
+ }
+ &:focus {
+ background-color: #f3f2f1;
+ }
+ &:active {
+ color: #000000;
+ }
+ &:active .ms-Button-icon {
+ color: #004578;
+ }
+ data-index="1"
+ data-is-focusable="true"
+ id="ComboBox0-list1"
+ role="option"
+ type="button"
>
- Header
-
+
+
+
+ Option 1
+
+
+
+
+
@@ -960,638 +1098,684 @@ exports[`ComboBox Renders correctly when open 1`] = `
word-wrap: break-word;
}
>
- Option 1
+ Option 2
-
-
* {
- left: 0px;
- position: relative;
- top: 0px;
- }
- @media screen and (-ms-high-contrast: active), (forced-colors: active){& {
- -ms-high-contrast-adjust: none;
- background-color: Highlight;
- border-color: Highlight;
- border: none;
- color: HighlightText;
- forced-color-adjust: none;
- }
- &.ms-Checkbox {
- align-items: center;
- display: flex;
- }
- &.ms-Button--command:hover:active {
- background-color: #edebe9;
- }
- & .ms-Checkbox-label {
- width: 100%;
- }
- &:hover {
- background-color: #f3f2f1;
- }
- @media screen and (-ms-high-contrast: active), (forced-colors: active){&:hover {
- -ms-high-contrast-adjust: none;
- background-color: Highlight;
- border-color: Highlight;
- color: HighlightText;
- forced-color-adjust: none;
- }
- .ms-Fabric--isFocusVisible &:after {
- border: 1px solid #ffffff;
- bottom: 0px;
- content: "";
- left: 0px;
- outline: 1px solid #605e5c;
- position: absolute;
- right: 0px;
- top: 0px;
- z-index: 1;
- }
- data-index="3"
- data-is-focusable="true"
- id="ComboBox0-list3"
- role="option"
- type="button"
- >
-
-
-
- Option 2
-
-
-
-
-
-
+
+
`;
exports[`ComboBox Renders correctly when opened in multi-select mode 1`] = `
-
+
-
- * {
- left: 0px;
+ &:active {
position: relative;
- top: 0px;
}
- @media screen and (-ms-high-contrast: active), (forced-colors: active){& {
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:active {
-ms-high-contrast-adjust: none;
- background-color: Highlight;
- border-color: Highlight;
+ background-color: Window;
color: HighlightText;
forced-color-adjust: none;
}
- &:hover {
- background-color: #e1dfdd;
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:active:after {
+ border-color: Highlight;
+ }
+ &:focus {
+ border-color: #0078d4;
+ }
+ &:focus .ms-ComboBox-Input {
color: #201f1e;
}
- @media screen and (-ms-high-contrast: active), (forced-colors: active){&:hover {
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:focus .ms-ComboBox-Input {
-ms-high-contrast-adjust: none;
- background-color: Highlight;
- border-color: Highlight;
+ background-color: Window;
+ color: WindowText;
+ forced-color-adjust: none;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:focus {
+ -ms-high-contrast-adjust: none;
+ background-color: Window;
color: HighlightText;
forced-color-adjust: none;
}
- data-is-focusable="false"
- role="presentation"
- tabindex="-1"
- type="button"
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:focus:after {
+ border-color: Highlight;
+ }
+ &:focus:after {
+ border-radius: 2px;
+ border: 2px solid #0078d4;
+ bottom: 0px;
+ content: '';
+ left: 0px;
+ pointer-events: none;
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ }
+ data-ktp-target="true"
+ id="ComboBox0wrapper"
>
-
+ * {
+ left: 0px;
+ position: relative;
+ top: 0px;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){& {
+ -ms-high-contrast-adjust: none;
+ background-color: Highlight;
+ border-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
+ }
+ &:hover {
+ background-color: #e1dfdd;
+ color: #201f1e;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:hover {
+ -ms-high-contrast-adjust: none;
+ background-color: Highlight;
+ border-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
+ }
+ data-is-focusable="false"
+ role="presentation"
+ tabindex="-1"
+ type="button"
>
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
- Header
-
+ role="separator"
+ />
@@ -1711,13 +1904,15 @@ exports[`ComboBox Renders correctly when opened in multi-select mode 1`] = `
right: 0px;
top: 0px;
}
- for="ComboBox0-list1"
+ for="ComboBox0-list3"
>
- Option 1
+ Option 2
-
-
-
-
-
-
-
+
+
`;
exports[`ComboBox renders with a Keytip correctly 1`] = `
-
+
-
- * {
- left: 0px;
+ &:active {
position: relative;
- top: 0px;
}
- @media screen and (-ms-high-contrast: active), (forced-colors: active){& {
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:active {
-ms-high-contrast-adjust: none;
- background-color: ButtonFace;
- border-color: ButtonText;
- color: ButtonText;
+ background-color: Window;
+ color: HighlightText;
forced-color-adjust: none;
}
- &:hover {
- background-color: #f3f2f1;
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:active:after {
+ border-color: Highlight;
+ }
+ &:focus {
+ border-color: #0078d4;
+ }
+ &:focus .ms-ComboBox-Input {
color: #201f1e;
- cursor: pointer;
}
- @media screen and (-ms-high-contrast: active), (forced-colors: active){&:hover {
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:focus .ms-ComboBox-Input {
-ms-high-contrast-adjust: none;
- background-color: Highlight;
- border-color: Highlight;
- color: HighlightText;
+ background-color: Window;
+ color: WindowText;
forced-color-adjust: none;
}
- &:active {
- background-color: #edebe9;
- color: #201f1e;
- }
- @media screen and (-ms-high-contrast: active), (forced-colors: active){&:active {
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:focus {
-ms-high-contrast-adjust: none;
- background-color: Highlight;
- border-color: Highlight;
+ background-color: Window;
color: HighlightText;
forced-color-adjust: none;
}
- data-is-focusable="false"
- role="presentation"
- tabindex="-1"
- type="button"
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:focus:after {
+ border-color: Highlight;
+ }
+ &:focus:after {
+ border-radius: 2px;
+ border: 2px solid #0078d4;
+ bottom: 0px;
+ content: '';
+ left: 0px;
+ pointer-events: none;
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ }
+ data-ktp-target="ktp-a"
+ id="ComboBox0wrapper"
>
-
+ * {
+ left: 0px;
+ position: relative;
+ top: 0px;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){& {
+ -ms-high-contrast-adjust: none;
+ background-color: ButtonFace;
+ border-color: ButtonText;
+ color: ButtonText;
+ forced-color-adjust: none;
+ }
+ &:hover {
+ background-color: #f3f2f1;
+ color: #201f1e;
+ cursor: pointer;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:hover {
+ -ms-high-contrast-adjust: none;
+ background-color: Highlight;
+ border-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
}
- data-automationid="splitbuttonprimary"
+ &:active {
+ background-color: #edebe9;
+ color: #201f1e;
+ }
+ @media screen and (-ms-high-contrast: active), (forced-colors: active){&:active {
+ -ms-high-contrast-adjust: none;
+ background-color: Highlight;
+ border-color: Highlight;
+ color: HighlightText;
+ forced-color-adjust: none;
+ }
+ data-is-focusable="false"
+ role="presentation"
+ tabindex="-1"
+ type="button"
>
-
-
-
-
-
+
+
+
+
+
+
`;