diff --git a/packages/react/src/components/Slider/Slider.test.tsx b/packages/react/src/components/Slider/Slider.test.tsx index 6db2d567794e8..af9fe671a9918 100644 --- a/packages/react/src/components/Slider/Slider.test.tsx +++ b/packages/react/src/components/Slider/Slider.test.tsx @@ -1,28 +1,22 @@ import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import * as ReactTestUtils from 'react-dom/test-utils'; -import { mount, ReactWrapper } from 'enzyme'; -import { resetIds, KeyCodes } from '@fluentui/utilities'; -import { create } from '@fluentui/utilities/lib/test'; +import { resetIds } from '../../Utilities'; +import { fireEvent, render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { Slider } from './Slider'; import { isConformant } from '../../common/isConformant'; import type { ISlider } from './Slider.types'; const MIN_PREFIX = 'min'; const MAX_PREFIX = 'max'; +const DOWN = 'arrowdown'; +const UP = 'arrowup'; describe('Slider', () => { - let wrapper: ReactWrapper | undefined; - beforeEach(() => { resetIds(); }); afterEach(() => { - if (wrapper) { - wrapper.unmount(); - wrapper = undefined; - } if ((setTimeout as any).mock) { jest.useRealTimers(); } @@ -34,71 +28,68 @@ describe('Slider', () => { }); it('renders correctly', () => { - const component = create(); - const tree = component.toJSON(); - expect(tree).toMatchSnapshot(); + const { container } = render(); + expect(container).toMatchSnapshot(); }); it('renders range slider correctly', () => { - const component = create(); - const tree = component.toJSON(); - expect(tree).toMatchSnapshot(); + const { container } = render(); + expect(container).toMatchSnapshot(); }); it('can set aria-labelledby attribute', () => { - wrapper = mount(); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); - expect(sliderSlideBox.getDOMNode().getAttribute('aria-labelledby')).toEqual('custom-label'); + const { getByRole } = render(); + expect(getByRole('slider').getAttribute('aria-labelledby')).toBe('custom-label'); }); it('can provide the current value', () => { const slider = React.createRef(); - wrapper = mount(); + render(); expect(slider.current?.value).toEqual(12); }); it('can provide the current range', () => { const slider = React.createRef(); - wrapper = mount(); + render(); expect(slider.current?.range).toEqual([0, 12]); }); it('can set id', () => { - wrapper = mount(); + const { container, getByRole } = render(); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); - expect(sliderSlideBox.getDOMNode().id).toEqual('test_id'); + expect(getByRole('slider').id).toEqual('test_id'); // properly associates label with custom id - const label = wrapper.find('label.test_label'); - expect(label.prop('htmlFor')).toBe('test_id'); + const label = container.getElementsByClassName('test_label')[0]; + expect(label.getAttribute('for')).toBe('test_id'); }); it('can set id via buttonProps', () => { // Not the recommended way of doing things, but it should work consistently still - wrapper = mount(); + const { container, getByRole } = render( + , + ); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); - expect(sliderSlideBox.getDOMNode().id).toEqual('test_id'); + expect(getByRole('slider').id).toEqual('test_id'); // properly associates label with custom id - const label = wrapper.find('label.test_label'); - expect(label.prop('htmlFor')).toBe('test_id'); + const label = container.getElementsByClassName('test_label')[0]; + expect(label.getAttribute('for')).toBe('test_id'); }); it('handles zero default value', () => { const slider = React.createRef(); - wrapper = mount(); + render(); expect(slider.current!.value).toEqual(0); }); it('handles zero value', () => { const slider = React.createRef(); - wrapper = mount(); + render(); expect(slider.current!.value).toEqual(0); }); @@ -106,15 +97,17 @@ describe('Slider', () => { const onChange = jest.fn(); const onChanged = jest.fn(); const slider = React.createRef(); - wrapper = mount(); + const { container, getByRole } = render( + , + ); - const sliderLine = wrapper.find('.ms-Slider-line'); - const sliderThumb = wrapper.find('.ms-Slider-slideBox'); + const sliderLine = container.getElementsByClassName('ms-Slider-line')[0]; + const sliderThumb = getByRole('slider'); - sliderLine.getDOMNode().getBoundingClientRect = () => + sliderLine.getBoundingClientRect = () => ({ left: 0, top: 0, right: 100, bottom: 40, width: 100, height: 40 } as DOMRect); - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 0, clientY: 0 }); + fireEvent.mouseDown(sliderThumb, { clientX: 0, clientY: 0 }); // Default min is 0. expect(onChange).toHaveBeenCalledTimes(1); expect(onChange.mock.calls[0][0]).toEqual(0); @@ -122,7 +115,7 @@ describe('Slider', () => { expect(slider.current!.value).toBe(0); // have to use a real event to trigger onChanged - window.dispatchEvent(new Event('mouseup')); + fireEvent.mouseUp(sliderThumb); expect(onChange).toHaveBeenCalledTimes(1); // not called again expect(onChanged).toHaveBeenCalledTimes(1); expect(onChanged.mock.calls[0][1]).toEqual(0); @@ -132,22 +125,24 @@ describe('Slider', () => { const onChange = jest.fn(); const onChanged = jest.fn(); const slider = React.createRef(); - wrapper = mount(); + const { container } = render( + , + ); - const sliderLine = wrapper.find('.ms-Slider-line'); - const sliderThumb = wrapper.find('.ms-Slider-slideBox'); + const sliderLine = container.getElementsByClassName('ms-Slider-line')[0]; + const sliderThumb = container.getElementsByClassName('ms-Slider-slideBox')[0]; - sliderLine.getDOMNode().getBoundingClientRect = () => + sliderLine.getBoundingClientRect = () => ({ left: 0, top: 0, right: 100, bottom: 40, width: 100, height: 40 } as DOMRect); - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 0, clientY: 0 }); + fireEvent.mouseDown(sliderThumb, { clientX: 0, clientY: 0 }); // Default min is 0. expect(onChange).toHaveBeenCalledTimes(1); expect(onChange.mock.calls[0][1]).toEqual([0, 5]); expect(onChanged).toHaveBeenCalledTimes(0); expect(slider.current!.range).toEqual([0, 5]); - window.dispatchEvent(new Event('mouseup')); + fireEvent.mouseUp(sliderThumb); expect(onChange).toHaveBeenCalledTimes(1); expect(onChanged).toHaveBeenCalledTimes(1); expect(onChanged.mock.calls[0][2]).toEqual([0, 5]); @@ -156,40 +151,39 @@ describe('Slider', () => { it('does not call onChange or onChanged with range when ranged is false', () => { const onChange = jest.fn(); const onChanged = jest.fn(); - wrapper = mount(); + const { container } = render(); - const sliderLine = wrapper.find('.ms-Slider-line'); - const sliderThumb = wrapper.find('.ms-Slider-slideBox'); + const sliderLine = container.getElementsByClassName('ms-Slider-line')[0]; + const sliderThumb = container.getElementsByClassName('ms-Slider-slideBox')[0]; - sliderLine.getDOMNode().getBoundingClientRect = () => + sliderLine.getBoundingClientRect = () => ({ left: 0, top: 0, right: 100, bottom: 40, width: 100, height: 40 } as DOMRect); - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 0, clientY: 0 }); - + fireEvent.mouseDown(sliderThumb, { clientX: 0, clientY: 0 }); expect(onChange.mock.calls[0][1]).toBeUndefined(); - window.dispatchEvent(new Event('mouseup')); + fireEvent.mouseUp(sliderThumb); expect(onChanged.mock.calls[0][2]).toBeUndefined(); }); it('can slide to default min/max and execute onChange', () => { const onChange = jest.fn(); - wrapper = mount(); + const { container } = render(); - const sliderLine = wrapper.find('.ms-Slider-line'); - const sliderThumb = wrapper.find('.ms-Slider-slideBox'); + const sliderLine = container.getElementsByClassName('ms-Slider-line')[0]; + const sliderThumb = container.getElementsByClassName('ms-Slider-slideBox')[0]; - sliderLine.getDOMNode().getBoundingClientRect = () => + sliderLine.getBoundingClientRect = () => ({ left: 0, top: 0, right: 100, bottom: 40, width: 100, height: 40 } as DOMRect); - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 100, clientY: 0 }); + fireEvent.mouseDown(sliderThumb, { clientX: 100, clientY: 0 }); // Default max is 10. expect(onChange).toHaveBeenCalledTimes(1); expect(onChange.mock.calls[0][0]).toEqual(10); - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 0, clientY: 0 }); + fireEvent.mouseDown(sliderThumb, { clientX: 0, clientY: 0 }); // Default min is 0. expect(onChange).toHaveBeenCalledTimes(2); @@ -199,15 +193,15 @@ describe('Slider', () => { it('updates the upper value thumb when click to the right side of it', () => { const onChange = jest.fn(); - wrapper = mount(); + const { container } = render(); - const sliderLine = wrapper.find('.ms-Slider-line'); - const sliderThumb = wrapper.find('.ms-Slider-slideBox'); + const sliderLine = container.getElementsByClassName('ms-Slider-line')[0]; + const sliderThumb = container.getElementsByClassName('ms-Slider-slideBox')[0]; - sliderLine.getDOMNode().getBoundingClientRect = () => + sliderLine.getBoundingClientRect = () => ({ left: 0, top: 0, right: 100, bottom: 40, width: 100, height: 40 } as DOMRect); - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 80, clientY: 0 }); + fireEvent.mouseDown(sliderThumb, { clientX: 80, clientY: 0 }); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange.mock.calls[0][1]).toEqual([0, 8]); @@ -216,15 +210,15 @@ describe('Slider', () => { it('updates the upper value thumb when click close to it', () => { const onChange = jest.fn(); - wrapper = mount(); + const { container } = render(); - const sliderLine = wrapper.find('.ms-Slider-line'); - const sliderThumb = wrapper.find('.ms-Slider-slideBox'); + const sliderLine = container.getElementsByClassName('ms-Slider-line')[0]; + const sliderThumb = container.getElementsByClassName('ms-Slider-slideBox')[0]; - sliderLine.getDOMNode().getBoundingClientRect = () => + sliderLine.getBoundingClientRect = () => ({ left: 0, top: 0, right: 100, bottom: 40, width: 100, height: 40 } as DOMRect); - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 40, clientY: 0 }); + fireEvent.mouseDown(sliderThumb, { clientX: 40, clientY: 0 }); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange.mock.calls[0][1]).toEqual([0, 4]); @@ -234,21 +228,21 @@ describe('Slider', () => { const onChange = jest.fn(); const onChanged = jest.fn(); - wrapper = mount(); + const { container } = render(); - const sliderLine = wrapper.find('.ms-Slider-line'); - const sliderThumb = wrapper.find('.ms-Slider-slideBox'); + const sliderLine = container.getElementsByClassName('ms-Slider-line')[0]; + const sliderThumb = container.getElementsByClassName('ms-Slider-slideBox')[0]; - sliderLine.getDOMNode().getBoundingClientRect = () => + sliderLine.getBoundingClientRect = () => ({ left: 0, top: 0, right: 100, bottom: 40, width: 100, height: 40 } as DOMRect); - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 10, clientY: 0 }); + fireEvent.mouseDown(sliderThumb, { clientX: 10, clientY: 0 }); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange.mock.calls[0][1]).toEqual([1, 5]); // test onChanged here too, since the earlier tests don't cover the lower thumb - window.dispatchEvent(new Event('mouseup')); + fireEvent.mouseUp(sliderThumb); expect(onChanged).toHaveBeenCalledTimes(1); expect(onChanged.mock.calls[0][2]).toEqual([1, 5]); }); @@ -259,104 +253,89 @@ describe('Slider', () => { range = sliderRange; }; - wrapper = mount(); + const { container } = render(); - const sliderLine = wrapper.find('.ms-Slider-line'); - const sliderThumb = wrapper.find('.ms-Slider-slideBox'); + const sliderLine = container.getElementsByClassName('ms-Slider-line')[0]; + const sliderThumb = container.getElementsByClassName('ms-Slider-slideBox')[0]; - sliderLine.getDOMNode().getBoundingClientRect = () => + sliderLine.getBoundingClientRect = () => ({ left: 0, top: 0, right: 100, bottom: 40, width: 100, height: 40 } as DOMRect); - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 10, clientY: 0 }); - - sliderThumb.simulate('mousedown', { type: 'mousedown', clientX: 20, clientY: 0 }); + fireEvent.mouseDown(sliderThumb, { clientX: 10, clientY: 0 }); + fireEvent.mouseDown(sliderThumb, { clientX: 20, clientY: 0 }); expect(range).toEqual([2, 5]); }); - it('has type=button on all buttons', () => { - wrapper = mount(); - - wrapper.find('button').forEach(button => { - expect(button.prop('type')).toEqual('button'); - }); - }); - it('renders correct aria-valuetext', () => { - wrapper = mount(); + const { getByRole, rerender } = render(); - expect(wrapper.find('.ms-Slider-slideBox').prop('aria-valuetext')).toEqual('0'); + expect(getByRole('slider').getAttribute('aria-valuetext')).toEqual('0'); const values = ['small', 'medium', 'large']; const selected = 1; const getTextValue = (value: number) => values[value]; - wrapper.unmount(); - wrapper = mount(); + rerender(); - expect(wrapper.find('.ms-Slider-slideBox').prop('aria-valuetext')).toEqual(values[selected]); + expect(getByRole('slider').getAttribute('aria-valuetext')).toEqual(values[selected]); }); it('renders correct aria properties for range slider', () => { - wrapper = mount(); + const { getAllByRole } = render(); - const lowerValueThumb = wrapper.find('.ms-Slider-thumb').at(0); + const lowerValueThumb = getAllByRole('slider')[0]; - expect(lowerValueThumb.prop('aria-valuemax')).toEqual(5); - expect(lowerValueThumb.prop('aria-valuemin')).toEqual(0); - expect(lowerValueThumb.prop('aria-valuenow')).toEqual(0); - expect(lowerValueThumb.prop('aria-label')).toEqual(`${MIN_PREFIX} range`); + expect(lowerValueThumb.getAttribute('aria-valuemax')).toEqual('5'); + expect(lowerValueThumb.getAttribute('aria-valuemin')).toEqual('0'); + expect(lowerValueThumb.getAttribute('aria-valuenow')).toEqual('0'); + expect(lowerValueThumb.getAttribute('aria-label')).toEqual(`${MIN_PREFIX} range`); - const upperValueThumb = wrapper.find('.ms-Slider-thumb').at(1); + const upperValueThumb = getAllByRole('slider')[1]; - expect(upperValueThumb.prop('aria-valuemax')).toEqual(10); - expect(upperValueThumb.prop('aria-valuemin')).toEqual(0); - expect(upperValueThumb.prop('aria-valuenow')).toEqual(5); - expect(upperValueThumb.prop('aria-label')).toEqual(`${MAX_PREFIX} range`); + expect(upperValueThumb.getAttribute('aria-valuemax')).toEqual('10'); + expect(upperValueThumb.getAttribute('aria-valuemin')).toEqual('0'); + expect(upperValueThumb.getAttribute('aria-valuenow')).toEqual('5'); + expect(upperValueThumb.getAttribute('aria-label')).toEqual(`${MAX_PREFIX} range`); }); it('formats the value when a format function is passed', () => { const value = 10; const valueFormat = (val: number) => `${val}%`; - wrapper = mount(); + const { container } = render(); - expect(wrapper.find('label.ms-Label.ms-Slider-value').text()).toEqual(valueFormat(value)); + expect(container.getElementsByClassName('ms-Slider-value')[0].textContent).toEqual(valueFormat(value)); }); - it('updates value correctly when down and up are pressed', () => { + it('updates value of upperthumb for range slider correctly when down and up are pressed', () => { const slider = React.createRef(); const onChange = jest.fn(); - wrapper = mount( + render( , ); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); - sliderSlideBox.simulate('keydown', { which: KeyCodes.down }); - sliderSlideBox.simulate('keydown', { which: KeyCodes.down }); - sliderSlideBox.simulate('keydown', { which: KeyCodes.down }); - sliderSlideBox.simulate('keydown', { which: KeyCodes.up }); - sliderSlideBox.simulate('keydown', { which: KeyCodes.down }); + // move keyboard focus to upperthumb of slider + userEvent.tab({ shift: true }); + //press up and down keys to modify slider value + userEvent.keyboard(`{${DOWN}}{${DOWN}}{${DOWN}}{${UP}}{${DOWN}}`); expect(slider.current?.value).toEqual(9); expect(onChange).toHaveBeenCalledTimes(5); }); - it('updates value for range slider correctly when down and up are pressed', () => { + it('updates value of upperthumb for range slider correctly when down and up are pressed', () => { const slider = React.createRef(); const onChange = jest.fn(); - wrapper = mount( + render( , ); - const lowerValueThumb = wrapper.find('.ms-Slider-thumb').at(0); - lowerValueThumb.simulate('keydown', { which: KeyCodes.down }); - lowerValueThumb.simulate('keydown', { which: KeyCodes.down }); - lowerValueThumb.simulate('keydown', { which: KeyCodes.down }); - lowerValueThumb.simulate('keydown', { which: KeyCodes.up }); - lowerValueThumb.simulate('keydown', { which: KeyCodes.down }); + // move keyboard focus to upperthumb of slider + userEvent.tab({ shift: true }); + userEvent.keyboard(`{${DOWN}}{${DOWN}}{${DOWN}}{${UP}}{${DOWN}}`); expect(slider.current?.value).toEqual(17); @@ -367,17 +346,11 @@ describe('Slider', () => { jest.useFakeTimers(); const onChanged = jest.fn(); - const container = document.createElement('div'); - document.body.appendChild(container); + const { container } = render(); + const sliderSlideBox = container.getElementsByClassName('ms-Slider-slideBox')[0]; - ReactDOM.render(, container); - const sliderSlideBox = container.querySelector('.ms-Slider-slideBox') as HTMLElement; - - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.down }); - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.down }); - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.down }); - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.up }); - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.down }); + userEvent.tab(); + userEvent.keyboard(`{${DOWN}}{${DOWN}}{${DOWN}}{${UP}}{${DOWN}}`); expect(sliderSlideBox.getAttribute('aria-valuenow')).toEqual('9'); @@ -391,17 +364,10 @@ describe('Slider', () => { jest.useFakeTimers(); const onChanged = jest.fn(); - const container = document.createElement('div'); - document.body.appendChild(container); - - ReactDOM.render(, container); - const sliderSlideBox = container.querySelector('.ms-Slider-slideBox') as HTMLElement; + render(); - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.down }); - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.down }); - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.down }); - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.up }); - ReactTestUtils.Simulate.keyDown(sliderSlideBox, { which: KeyCodes.down }); + userEvent.tab(); + userEvent.keyboard(`{${DOWN}}{${DOWN}}{${DOWN}}{${UP}}{${DOWN}}`); // onChanged should only be called after a delay expect(onChanged).toHaveBeenCalledTimes(0); @@ -414,10 +380,10 @@ describe('Slider', () => { const slider = React.createRef(); const onChange = jest.fn(); - wrapper = mount(); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); + render(); - sliderSlideBox.simulate('keydown', { which: KeyCodes.down }); + userEvent.tab(); + userEvent.keyboard(`{${DOWN}}`); expect(slider.current?.value).toEqual(3); @@ -428,10 +394,10 @@ describe('Slider', () => { const slider = React.createRef(); const onChange = jest.fn(); - wrapper = mount(); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); + render(); - sliderSlideBox.simulate('keydown', { which: KeyCodes.down }); + userEvent.tab(); + userEvent.keyboard(`{${DOWN}}`); expect(slider.current?.value).toEqual(3); @@ -443,12 +409,11 @@ describe('Slider', () => { const slider = React.createRef(); const onChange = jest.fn(); - wrapper = mount( - , - ); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); + render(); - sliderSlideBox.simulate('keydown', { which: KeyCodes.down }); + // move keyboard focus to upperthumb of slider + userEvent.tab({ shift: true }); + userEvent.keyboard(`{${DOWN}}`); expect(slider.current?.range).toEqual([0, 3]); @@ -460,12 +425,10 @@ describe('Slider', () => { const slider = React.createRef(); const onChange = jest.fn(); - wrapper = mount(); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); + render(); - sliderSlideBox.simulate('keydown', { which: KeyCodes.up }); - sliderSlideBox.simulate('keydown', { which: KeyCodes.up }); - sliderSlideBox.simulate('keydown', { which: KeyCodes.up }); + userEvent.tab(); + userEvent.keyboard(`{${UP}}{${UP}}{${UP}}`); expect(slider.current?.value).toEqual(3); @@ -477,23 +440,23 @@ describe('Slider', () => { const slider = React.createRef(); const onChange = jest.fn(); - wrapper = mount( + render( , ); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); - sliderSlideBox.simulate('keydown', { which: KeyCodes.up }); + userEvent.tab(); + userEvent.keyboard(`{${UP}}`); + expect(slider.current?.value).toEqual(7); }); it('correctly changes value with decimal steps', () => { - const container = document.createElement('div'); const slider = React.createRef(); const onChange = jest.fn(); const step = 0.0000001; const defaultValue = 10; - wrapper = mount( + render( { onChange={onChange} />, ); - const sliderSlideBox = wrapper.find('.ms-Slider-slideBox'); - sliderSlideBox.simulate('keydown', { which: KeyCodes.up }); + userEvent.tab(); + userEvent.keyboard(`{${UP}}`); + expect(slider.current?.value).toEqual(defaultValue + step); - ReactDOM.unmountComponentAtNode(container); }); }); diff --git a/packages/react/src/components/Slider/__snapshots__/Slider.test.tsx.snap b/packages/react/src/components/Slider/__snapshots__/Slider.test.tsx.snap index 9518ddf35f657..1747cf9228bc9 100644 --- a/packages/react/src/components/Slider/__snapshots__/Slider.test.tsx.snap +++ b/packages/react/src/components/Slider/__snapshots__/Slider.test.tsx.snap @@ -1,350 +1,296 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Slider renders correctly 1`] = ` - - + - I am a slider - - + + I am a slider + - - - - + + > + + + + + + + 0 + - - 0 - `; exports[`Slider renders range slider correctly 1`] = ` - - + - I am a ranged slider - - - 0 + I am a ranged slider + + 0 + - - - - - + + > + + + + + + + + 5 + - - 5 - `;