Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
setupFilesAfterEnv: ['./config/jest.setup.ts'],
moduleNameMapper: {
'^components(.*)$': '<rootDir>/src/component$1',
'^components(.*)$': '<rootDir>/src/components$1',
'^hooks(.*)$': '<rootDir>/src/hooks$1',
'^utils(.*)$': '<rootDir>/src/utils$1',
},
Expand Down
6 changes: 3 additions & 3 deletions src/components/RangeSlider/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ const renderRangeSlider = (propOverrides: Partial<IRangeSlider> = {}) => {
)

const getTrackElement = () => {
return wrapper.getByTestId('range-track')
return wrapper.getByTestId('range-slider-track')
}

const getMinThumbElement = () => {
return wrapper.getByTestId('range-min-thumb')
return wrapper.getByTestId('range-slider-min-thumb')
}

const getMaxThumbElement = () => {
return wrapper.getByTestId('range-max-thumb')
return wrapper.getByTestId('range-slider-max-thumb')
}

return {
Expand Down
18 changes: 8 additions & 10 deletions src/components/RangeSlider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
SliderThumb,
SliderMarker,
SliderMarkerLabel,
} from './styled'
} from '../styled'

import { useRangeSlider } from 'hooks/useRangeSlider'

Expand Down Expand Up @@ -48,23 +48,21 @@ const RangeSlider: React.FC<IRangeSlider> = ({
return (
<SliderContainer>
<SliderRail {...getRailProps()} />
<SliderTrack data-testid="range-track" {...getTrackProps()} />
<SliderTrack data-testid="range-slider-track" {...getTrackProps()} />

{markers?.map((marker) => {
const { style, isInRange } = getMarkerProps(marker)

return (
<>
<SliderMarkerLabel key={`marker-label-${marker.label}`} style={style}>
{marker.label}
</SliderMarkerLabel>
<SliderMarker key={`marker-${marker.label}`} isInRange={isInRange} style={style} />
</>
<React.Fragment key={`marker-${marker.label}`}>
<SliderMarkerLabel style={style}>{marker.label}</SliderMarkerLabel>
<SliderMarker isInRange={isInRange} style={style} />
</React.Fragment>
)
})}

<SliderThumb data-testid="range-min-thumb" {...getMinHandleProps()} />
<SliderThumb data-testid="range-max-thumb" {...getMaxHandleProps()} />
<SliderThumb data-testid="range-slider-min-thumb" {...getMinHandleProps()} />
<SliderThumb data-testid="range-slider-max-thumb" {...getMaxHandleProps()} />
</SliderContainer>
)
}
Expand Down
59 changes: 59 additions & 0 deletions src/components/Slider/__stories__/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react'
import styled from 'styled-components'

import { Slider } from '..'

const useSliderDemo = (initialValue = 0) => {
const [range, setRange] = React.useState<number>(initialValue)

return [range, setRange] as const
}

const DemoContainer = styled.div`
margin-top: 10rem;
padding: 0 5rem;
`

const demoMarkers = [
{ label: '$0', value: 0 },
{ label: '$25', value: 25 },
{ label: '$50', value: 50 },
{ label: '$75', value: 75 },
{ label: '$100', value: 100 },
]

const Basic = () => {
const [value, setValue] = useSliderDemo()

return (
<DemoContainer>
<Slider value={value} min={0} max={100} onChange={setValue} />
<pre>{JSON.stringify({ value }, null, 2)}</pre>
</DemoContainer>
)
}

const WithStep = () => {
const [value, setValue] = useSliderDemo(50)

return (
<DemoContainer>
<Slider value={value} min={0} max={1000} step={100} onChange={setValue} />
<pre>{JSON.stringify({ values: value }, null, 2)}</pre>
</DemoContainer>
)
}

const WithMarkers = () => {
const [value, setValue] = useSliderDemo(50)

return (
<DemoContainer>
<Slider value={value} min={0} max={100} markers={demoMarkers} onChange={setValue} />
<pre>{JSON.stringify({ values: value }, null, 2)}</pre>
</DemoContainer>
)
}

export default { title: 'Slider' }
export { Basic, WithStep, WithMarkers }
76 changes: 76 additions & 0 deletions src/components/Slider/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react'
import { render, fireEvent, act } from '@testing-library/react'

import { Slider, ISliderProps } from '..'

const renderSlider = (propOverrides: Partial<ISliderProps> = {}) => {
const wrapper = render(
<Slider min={0} max={100} value={50} onChange={() => {}} {...propOverrides} />
)

const getTrackElement = () => {
return wrapper.getByTestId('slider-track')
}

const getThumbElement = () => {
return wrapper.getByTestId('slider-thumb')
}

return {
...wrapper,
getTrackElement,
getThumbElement,
}
}

describe('<Slider />', () => {
it('should be defined', () => {
expect(Slider).toBeDefined()
})

it('should render a Range Slider with properly positioned thumbs and track', async () => {
const { getTrackElement, getThumbElement } = renderSlider()

const trackElement = getTrackElement()
const thumbElement = getThumbElement()

expect(trackElement).toHaveStyle('width: 50%')
expect(thumbElement).toHaveStyle('left: 50%')
})

it('should render Range Slider markers', () => {
const { getByText } = renderSlider({
markers: [
{ value: 0, label: '$0' },
{ value: 100, label: '$100' },
],
})

getByText('$0')
getByText('$100')
})

describe('user interaction', () => {
// TODO: find out how to set container size in testing environment
it.skip('should trigger onChange with appropriate data when moving with min thumb', () => {
const onChangeSpy = jest.fn()

const { getThumbElement } = renderSlider({
min: 0,
max: 100,
value: 0,
onChange: onChangeSpy,
})

const thumbElement = getThumbElement()

act(() => {
fireEvent.mouseDown(thumbElement, { clientX: 0 })
fireEvent.mouseMove(thumbElement, { clientX: 50 })
fireEvent.mouseUp(thumbElement)
})

expect(onChangeSpy).toHaveBeenCalledWith([10, 100])
})
})
})
56 changes: 56 additions & 0 deletions src/components/Slider/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react'

import {
SliderContainer,
SliderRail,
SliderTrack,
SliderThumb,
SliderMarkerLabel,
SliderMarker,
} from '../styled'

import { useSlider } from 'hooks/useSlider'

import { IRangeMarker } from 'types'

export interface ISliderProps {
value: number
min: number
max: number
onChange: (value: number) => void

step?: number
markers?: IRangeMarker[]
}

const Slider: React.FC<ISliderProps> = ({ value, min, max, onChange, step, markers }) => {
const { getRailProps, getTrackProps, getHandleProps, getMarkerProps } = useSlider({
value,
min,
max,
onChange,
step,
})

return (
<SliderContainer>
<SliderRail {...getRailProps()} />
<SliderTrack data-testid="slider-track" {...getTrackProps()} />

{markers?.map((marker) => {
const { style, isInRange } = getMarkerProps(marker)

return (
<React.Fragment key={`marker-${marker.label}`}>
<SliderMarkerLabel style={style}>{marker.label}</SliderMarkerLabel>
<SliderMarker isInRange={isInRange} style={style} />
</React.Fragment>
)
})}

<SliderThumb data-testid="slider-thumb" {...getHandleProps()} />
</SliderContainer>
)
}

export { Slider }
File renamed without changes.
2 changes: 1 addition & 1 deletion src/hooks/useRangeSlider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

const DEFAULT_STEP = 1

interface IUseRangeSlider {
export interface IUseRangeSlider {
value: TRangeTuple
min: number
max: number
Expand Down
Loading