Skip to content

Commit

Permalink
WIP tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mj12albert committed May 16, 2024
1 parent f95c8a8 commit 34fb90b
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 1 deletion.
167 changes: 167 additions & 0 deletions packages/mui-base/src/Slider2/Root/SliderRoot.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
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.Track>
<Slider.Thumb />
</Slider.Track>
</Slider.Root>,
);

expect(screen.getByRole('slider')).to.have.attribute('aria-valuenow', '30');
});

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);
});
});
});
2 changes: 2 additions & 0 deletions packages/mui-base/src/Slider2/Root/SliderRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const SliderRoot = React.forwardRef(function SliderRoot(
disabled = false,
render: renderProp,
onValueChange,
orientation,
value,
...otherProps
} = props;
Expand All @@ -34,6 +35,7 @@ const SliderRoot = React.forwardRef(function SliderRoot(
defaultValue,
disabled,
onValueChange,
orientation,
rootRef: mergedRef,
value,
...otherProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export function useSliderThumb(parameters: UseSliderThumbParameters) {
'aria-orientation': orientation,
'aria-valuemax': scale(max),
'aria-valuemin': scale(min),
'aria-valuenow': scale(thumbValue),
disabled,
name,
id: compoundItemId,
Expand Down
13 changes: 13 additions & 0 deletions packages/mui-base/src/Slider2/SliderTrack/SliderTrack.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,16 @@ import { BaseUIComponentProps } from '../../utils/BaseUI.types';
import { SliderRootOwnerState } from '../Root/SliderRoot.types';

export interface SliderTrackProps extends BaseUIComponentProps<'div', SliderRootOwnerState> {}

export interface UseSliderTrackParameters {
/**
* The ref attached to the track of the Slider.
*/
rootRef?: React.Ref<Element>;
}

export interface UseSliderTrackReturnValue {
getRootProps: (
externalProps?: React.ComponentPropsWithRef<'div'>,
) => React.ComponentPropsWithRef<'div'>;
}
3 changes: 2 additions & 1 deletion packages/mui-base/src/Slider2/SliderTrack/useSliderTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import { useSliderContext } from '../Root/SliderContext';
import { useEventCallback } from '../../utils/useEventCallback';
import { roundValueToStep, valueToPercent } from '../utils';
import { areValuesEqual, focusThumb, trackFinger } from '../Root/useSliderRoot';
import { UseSliderTrackParameters, UseSliderTrackReturnValue } from './SliderTrack.types';

const INTENTIONAL_DRAG_COUNT_THRESHOLD = 2;

export function useSliderTrack(parameters: any) {
export function useSliderTrack(parameters: UseSliderTrackParameters): UseSliderTrackReturnValue {
const { rootRef: externalRef } = parameters;

const trackRef = React.useRef<HTMLElement>(null);
Expand Down

0 comments on commit 34fb90b

Please sign in to comment.