forked from mui/base-ui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f95c8a8
commit c90b682
Showing
5 changed files
with
219 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
import { expect } from 'chai'; | ||
import * as React from 'react'; | ||
import { spy, stub } from 'sinon'; | ||
import { act, createRenderer, fireEvent, screen } from '@mui/internal-test-utils'; | ||
import * as Slider from '@base_ui/react/Slider2'; | ||
import { describeConformance } from '../../../test/describeConformance'; | ||
|
||
type Touches = Array<Pick<Touch, 'identifier' | 'clientX' | 'clientY'>>; | ||
|
||
function createTouches(touches: Touches) { | ||
return { | ||
changedTouches: touches.map( | ||
(touch) => | ||
new Touch({ | ||
target: document.body, | ||
...touch, | ||
}), | ||
), | ||
}; | ||
} | ||
|
||
describe('<Slider.Root />', () => { | ||
before(function beforeHook() { | ||
if (typeof Touch === 'undefined') { | ||
this.skip(); | ||
} | ||
|
||
// PointerEvent not fully implemented in jsdom, causing | ||
// fireEvent.pointer* to ignore options | ||
// https://github.com/jsdom/jsdom/issues/2527 | ||
(window as any).PointerEvent = window.MouseEvent; | ||
}); | ||
|
||
const { render } = createRenderer(); | ||
|
||
describeConformance(<Slider.Root defaultValue={50} />, () => ({ | ||
inheritComponent: 'div', | ||
render, | ||
refInstanceof: window.HTMLDivElement, | ||
})); | ||
|
||
it('renders a slider', () => { | ||
render( | ||
<Slider.Root defaultValue={30}> | ||
<Slider.Output /> | ||
<Slider.Track> | ||
<Slider.Thumb /> | ||
</Slider.Track> | ||
</Slider.Root>, | ||
); | ||
|
||
expect(screen.getByRole('slider')).to.have.attribute('aria-valuenow', '30'); | ||
}); | ||
|
||
describe('ARIA attributes', () => { | ||
it('it has the correct aria attributes', () => { | ||
const { container, getByRole, getByTestId } = render( | ||
<Slider.Root defaultValue={30} aria-labelledby="labelId" data-testid="root"> | ||
<Slider.Output /> | ||
<Slider.Track> | ||
<Slider.Thumb /> | ||
</Slider.Track> | ||
</Slider.Root>, | ||
); | ||
|
||
const root = getByTestId('root'); | ||
const slider = getByRole('slider'); | ||
const input = container.querySelector('input'); | ||
|
||
expect(root).not.to.have.attribute('aria-labelledby'); | ||
|
||
expect(slider).to.have.attribute('aria-valuenow', '30'); | ||
expect(slider).to.have.attribute('aria-valuemin', '0'); | ||
expect(slider).to.have.attribute('aria-valuemax', '100'); | ||
expect(slider).to.have.attribute('aria-orientation', 'horizontal'); | ||
|
||
expect(input).to.have.attribute('aria-labelledby', 'labelId'); | ||
expect(input).to.have.attribute('aria-valuenow', '30'); | ||
|
||
// TODO: aria-label should be somewhere | ||
}); | ||
}); | ||
|
||
describe('prop: disabled', () => {}); | ||
|
||
describe('prop: marks', () => { | ||
it('does not cause unknown-prop error', () => { | ||
const marks = [ | ||
{ | ||
value: 33, | ||
}, | ||
]; | ||
expect(() => { | ||
render(<Slider.Root marks={marks} />); | ||
}).not.to.throw(); | ||
}); | ||
}); | ||
|
||
describe('prop: orientation', () => { | ||
function VerticalSlider() { | ||
return ( | ||
<Slider.Root orientation="vertical"> | ||
<Slider.Track> | ||
<Slider.Thumb /> | ||
</Slider.Track> | ||
</Slider.Root> | ||
); | ||
} | ||
|
||
it('sets the orientation via ARIA', () => { | ||
render(<VerticalSlider />); | ||
|
||
const sliderRoot = screen.getByRole('slider'); | ||
expect(sliderRoot).to.have.attribute('aria-orientation', 'vertical'); | ||
}); | ||
|
||
it('does not set the orientation via appearance for WebKit browsers', function test() { | ||
if (/jsdom/.test(window.navigator.userAgent) || !/WebKit/.test(window.navigator.userAgent)) { | ||
this.skip(); | ||
} | ||
|
||
render(<VerticalSlider />); | ||
|
||
const slider = screen.getByRole('slider'); | ||
|
||
expect(slider).to.have.property('tagName', 'INPUT'); | ||
expect(slider).to.have.property('type', 'range'); | ||
// Only relevant if we implement `[role="slider"]` with `input[type="range"]` | ||
// We're not setting this by default because it changes horizontal keyboard navigation in WebKit: https://bugs.chromium.org/p/chromium/issues/detail?id=1162640 | ||
expect(slider).not.toHaveComputedStyle({ webkitAppearance: 'slider-vertical' }); | ||
}); | ||
}); | ||
|
||
describe('prop: onValueChange', () => { | ||
function TestSlider(props: { onValueChange: () => void }) { | ||
return ( | ||
<Slider.Root defaultValue={50} {...props}> | ||
<Slider.Track data-testid="track"> | ||
<Slider.Thumb data-testid="thumb" /> | ||
</Slider.Track> | ||
</Slider.Root> | ||
); | ||
} | ||
|
||
it('is called when clicking on the track', () => { | ||
const handleValueChange = spy(); | ||
render(<TestSlider onValueChange={handleValueChange} />); | ||
|
||
const sliderTrack = screen.getByTestId('track'); | ||
|
||
stub(sliderTrack, 'getBoundingClientRect').callsFake(() => ({ | ||
width: 100, | ||
height: 10, | ||
bottom: 10, | ||
left: 0, | ||
x: 0, | ||
y: 0, | ||
right: 0, | ||
top: 0, | ||
toJSON() {}, | ||
})); | ||
|
||
fireEvent.pointerDown(sliderTrack, { | ||
buttons: 1, | ||
clientX: 41, | ||
clientY: 5, | ||
}); | ||
|
||
expect(handleValueChange.callCount).to.equal(1); | ||
}); | ||
|
||
it('is not called when clicking on the thumb', () => { | ||
const handleValueChange = spy(); | ||
render(<TestSlider onValueChange={handleValueChange} />); | ||
|
||
const sliderTrack = screen.getByTestId('track'); | ||
const sliderThumb = screen.getByTestId('thumb'); | ||
|
||
stub(sliderTrack, 'getBoundingClientRect').callsFake(() => ({ | ||
width: 100, | ||
height: 10, | ||
bottom: 10, | ||
left: 0, | ||
x: 0, | ||
y: 0, | ||
right: 0, | ||
top: 0, | ||
toJSON() {}, | ||
})); | ||
|
||
fireEvent.pointerDown(sliderThumb, { | ||
buttons: 1, | ||
clientX: 51, | ||
}); | ||
|
||
expect(handleValueChange.callCount).to.equal(0); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters