Skip to content

Commit 2de3cff

Browse files
author
Hector Arce De Las Heras
committed
Include Slider component
1 parent 682dcac commit 2de3cff

29 files changed

+3161
-0
lines changed

src/components/slider/__tests__/slider.test.tsx

Lines changed: 589 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
import {
2+
calcNewRangeValue,
3+
calcScaleValue,
4+
calcValueByOffset,
5+
calculateChange,
6+
equalsRangeValues,
7+
shouldUpdateLeftThumb,
8+
shouldUpdateRightThumb,
9+
} from '../utils';
10+
11+
describe('Slider utils - equalsRangeValues', () => {
12+
it('return false when array length is different', () => {
13+
const areEquals = equalsRangeValues([1, 2], [1, 2, 3]);
14+
expect(areEquals).toBeFalsy();
15+
});
16+
17+
it('return false when array are differents', () => {
18+
const areEquals = equalsRangeValues([1, 2], [1, 4]);
19+
expect(areEquals).toBeFalsy();
20+
});
21+
22+
it('return true when array are equals', () => {
23+
const areEquals = equalsRangeValues([1, 2], [1, 2]);
24+
expect(areEquals).toBeTruthy();
25+
});
26+
});
27+
28+
describe('Slider utils - shouldUpdateLeftThumb', () => {
29+
it('return true if the newValue is less or equal than prevValue[0]', () => {
30+
const shouldUpdate = shouldUpdateLeftThumb('right', 1, [2, 2]);
31+
expect(shouldUpdate).toBeTruthy();
32+
});
33+
it('return true if the activePointer is the left one and the new value less than prevValue[1]', () => {
34+
const shouldUpdate = shouldUpdateLeftThumb('left', 1, [2, 2]);
35+
expect(shouldUpdate).toBeTruthy();
36+
});
37+
});
38+
39+
describe('Slider utils - shouldUpdateRightThumb', () => {
40+
it('return true if the newValue is greater or equal than prevValue[1]', () => {
41+
const shouldUpdate = shouldUpdateRightThumb('left', 3, [1, 2]);
42+
expect(shouldUpdate).toBeTruthy();
43+
});
44+
it('return true if the activePointer is the right one and the new value greater than prevValue[0]', () => {
45+
const shouldUpdate = shouldUpdateRightThumb('right', 3, [1, 2]);
46+
expect(shouldUpdate).toBeTruthy();
47+
});
48+
});
49+
50+
describe('Slider utils - calcNewRangeValue', () => {
51+
it('When shouldUpdateLeftThumb is true, return the new range value with the new value in the first position', () => {
52+
const newRangeValue = calcNewRangeValue([2, 4], 1, { current: 'left' });
53+
expect(newRangeValue).toEqual([1, 4]);
54+
});
55+
56+
it('When shouldUpdateLeftThumb, but the current active pointer is the right one, the active pointer changes to left', () => {
57+
const activePointer = { current: 'right' };
58+
const newRangeValue = calcNewRangeValue([2, 4], 1, activePointer);
59+
expect(newRangeValue).toEqual([1, 4]);
60+
expect(activePointer.current).toEqual('left');
61+
});
62+
63+
it('When shouldUpdateRightThumb is true, return the new range value with the new value in the second position', () => {
64+
const newRangeValue = calcNewRangeValue([2, 4], 3, { current: 'right' });
65+
expect(newRangeValue).toEqual([2, 3]);
66+
});
67+
68+
it('When shouldUpdateRightThumb, but the current active pointer is the left one, the active pointer changes to left', () => {
69+
const activePointer = { current: 'left' };
70+
const newRangeValue = calcNewRangeValue([2, 4], 6, activePointer);
71+
expect(newRangeValue).toEqual([2, 6]);
72+
expect(activePointer.current).toEqual('right');
73+
});
74+
75+
it('When no shouldUpdateLeftThumb nor shouldUpdateRightThumb', () => {
76+
const activePointer = { current: 'other' };
77+
const newRangeValue = calcNewRangeValue([2, 5], 4, activePointer);
78+
expect(newRangeValue).toEqual([2, 5]);
79+
});
80+
});
81+
82+
describe('Slider utils - calcScaleValue', () => {
83+
it('When step is 0 or less, return the value without changes', () => {
84+
// max: number, min: number, step: number, value: number
85+
const max = 10;
86+
const min = 0;
87+
const step = 0;
88+
const value = 5.5;
89+
const scaleValue = calcScaleValue(max, min, step, value);
90+
expect(scaleValue).toEqual(value);
91+
});
92+
});
93+
94+
describe('Slider utils - calcValueByOffset', () => {
95+
it('When step does not have decimals, return the value without decimals', () => {
96+
const max = 10;
97+
const min = 0;
98+
const step = 1;
99+
const offset = 50;
100+
const offsetBoundaries = { min: 0, max: 100 };
101+
const value = calcValueByOffset({ max, min, step, offset, offsetBoundaries });
102+
expect(value).toEqual(5);
103+
});
104+
it('When step has decimals, return the value with the same decimals as the step', () => {
105+
const max = 1;
106+
const min = 0;
107+
const step = 0.1;
108+
const offset = 50;
109+
const offsetBoundaries = { min: 0, max: 100 };
110+
const value = calcValueByOffset({ max, min, step, offset, offsetBoundaries });
111+
expect(value).toEqual(0.5);
112+
});
113+
});
114+
115+
describe('Slider utils - calculateChange', () => {
116+
let container: HTMLDivElement;
117+
let e: MouseEvent;
118+
119+
beforeEach(() => {
120+
container = document.createElement('div');
121+
Object.defineProperty(container, 'clientWidth', {
122+
configurable: true,
123+
// Define the property getter
124+
get() {
125+
return 100;
126+
},
127+
});
128+
129+
document.body.appendChild(container);
130+
131+
e = {
132+
pageX: 50,
133+
preventDefault: () => ({}),
134+
altKey: false,
135+
button: 0,
136+
buttons: 0,
137+
clientX: 0,
138+
clientY: 0,
139+
ctrlKey: false,
140+
metaKey: false,
141+
movementX: 0,
142+
movementY: 0,
143+
offsetX: 0,
144+
offsetY: 0,
145+
pageY: 0,
146+
relatedTarget: null,
147+
screenX: 0,
148+
screenY: 0,
149+
shiftKey: false,
150+
x: 0,
151+
y: 0,
152+
getModifierState: function (): boolean {
153+
throw new Error('Function not implemented.');
154+
},
155+
initMouseEvent: function (): void {
156+
throw new Error('Function not implemented.');
157+
},
158+
detail: 0,
159+
view: null,
160+
which: 0,
161+
initUIEvent: function (): void {
162+
throw new Error('Function not implemented.');
163+
},
164+
bubbles: false,
165+
cancelBubble: false,
166+
cancelable: false,
167+
composed: false,
168+
currentTarget: null,
169+
defaultPrevented: false,
170+
eventPhase: 0,
171+
isTrusted: false,
172+
returnValue: false,
173+
srcElement: null,
174+
target: null,
175+
timeStamp: 0,
176+
type: '',
177+
composedPath: function (): EventTarget[] {
178+
throw new Error('Function not implemented.');
179+
},
180+
initEvent: function (): void {
181+
throw new Error('Function not implemented.');
182+
},
183+
stopImmediatePropagation: function (): void {
184+
throw new Error('Function not implemented.');
185+
},
186+
stopPropagation: function (): void {
187+
throw new Error('Function not implemented.');
188+
},
189+
NONE: 0,
190+
CAPTURING_PHASE: 1,
191+
AT_TARGET: 2,
192+
BUBBLING_PHASE: 3,
193+
} as unknown as MouseEvent;
194+
});
195+
196+
afterEach(() => {
197+
document.body.removeChild(container);
198+
});
199+
200+
it('returns 0 when click is outside the left boundary', () => {
201+
Object.defineProperty(e, 'pageX', {
202+
configurable: true,
203+
// Define the property getter
204+
get() {
205+
return -5;
206+
},
207+
});
208+
209+
const offsetBoundaries = { min: 0, max: 100 };
210+
const result = calculateChange({ event: e, container, offsetBoundaries });
211+
expect(result).toBe(0);
212+
});
213+
214+
it('returns 100 when click is outside the right boundary', () => {
215+
Object.defineProperty(e, 'pageX', {
216+
configurable: true,
217+
// Define the property getter
218+
get() {
219+
return 105;
220+
},
221+
});
222+
const offsetBoundaries = { min: 0, max: 100 };
223+
const result = calculateChange({ event: e, container, offsetBoundaries });
224+
expect(result).toBe(100);
225+
});
226+
227+
it('returns correct offset when click is within the boundaries', () => {
228+
Object.defineProperty(e, 'pageX', {
229+
configurable: true,
230+
// Define the property getter
231+
get() {
232+
return 50;
233+
},
234+
});
235+
const offsetBoundaries = { min: 0, max: 100 };
236+
const result = calculateChange({ event: e, container, offsetBoundaries });
237+
expect(result).toBe(50);
238+
});
239+
240+
it('returns correct offset when click is within the boundaries when touchEvent', () => {
241+
const touch = {
242+
touches: [{ pageX: 50 }],
243+
preventDefault: () => ({}),
244+
} as unknown as React.TouchEvent<Element>;
245+
const offsetBoundaries = { min: 0, max: 100 };
246+
const result = calculateChange({ event: touch, container, offsetBoundaries });
247+
expect(result).toBe(50);
248+
});
249+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import * as React from 'react';
2+
3+
import { renderProvider } from 'tests/renderProvider/renderProvider.utility';
4+
5+
import { SliderHelperTextStandAlone } from '../components/sliderHelperTextStandAlone';
6+
import { SliderBaseStylesType, SliderStateType } from '../types';
7+
8+
const mockHelperTextProps = {
9+
styles: {} as SliderBaseStylesType,
10+
state: SliderStateType.DEFAULT,
11+
};
12+
13+
describe('<sliderHelperTextStandAlone />', () => {
14+
it('when no text, nothing should be render', () => {
15+
const { container } = renderProvider(<SliderHelperTextStandAlone {...mockHelperTextProps} />);
16+
expect(container).toBeEmptyDOMElement();
17+
});
18+
it('should render left and right helper text', () => {
19+
const { getByText } = renderProvider(
20+
<SliderHelperTextStandAlone
21+
{...mockHelperTextProps}
22+
leftHelperText="left"
23+
rightHelperText="right"
24+
/>
25+
);
26+
expect(getByText('left')).toBeInTheDocument();
27+
expect(getByText('right')).toBeInTheDocument();
28+
});
29+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import * as React from 'react';
2+
3+
import { renderProvider } from 'tests/renderProvider/renderProvider.utility';
4+
5+
import { SliderScaleStandAlone } from '../components/sliderScaleStandAlone';
6+
import { SliderBaseStylesType } from '../types';
7+
8+
const mockScaleProps = {
9+
showScale: true,
10+
scaleArray: [0, 1, 2, 3, 4, 5],
11+
max: 100,
12+
min: 1,
13+
step: 1,
14+
scaleCount: 100,
15+
style: undefined,
16+
styles: {} as SliderBaseStylesType,
17+
};
18+
19+
describe('<SliderScaleStandAlone />', () => {
20+
it('when showScale is false, nothing should be render', () => {
21+
const { container } = renderProvider(
22+
<SliderScaleStandAlone {...mockScaleProps} showScale={false} />
23+
);
24+
expect(container).toBeEmptyDOMElement();
25+
});
26+
it('when showScale is true, should be render', () => {
27+
const { container } = renderProvider(<SliderScaleStandAlone {...mockScaleProps} />);
28+
expect(container).not.toBeEmptyDOMElement();
29+
});
30+
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import userEvent from '@testing-library/user-event';
2+
3+
import * as React from 'react';
4+
5+
import { renderProvider } from 'tests/renderProvider/renderProvider.utility';
6+
7+
import { ROLES } from '@/types';
8+
9+
import { SliderStandAlone } from '../sliderStandAlone';
10+
import { SliderBaseStylesType } from '../types';
11+
12+
const mockSliderStandAlone = {
13+
// Original props
14+
range: false,
15+
min: 0,
16+
max: 100,
17+
step: 1,
18+
disabled: false,
19+
// Scale
20+
showScale: false,
21+
scaleArray: [],
22+
scaleCount: 0,
23+
// Generated props
24+
value: 50,
25+
offset: 50,
26+
offsetLeft: 0,
27+
offsetRight: 0,
28+
hover: false,
29+
pressed: false,
30+
activePointer: { current: '' },
31+
containerRef: { current: null },
32+
// Modifier functions
33+
onMouseDown: jest.fn(),
34+
onChange: jest.fn(),
35+
onTouchStart: jest.fn(),
36+
onKeyPress: jest.fn(),
37+
// Styles
38+
styles: { states: {} } as SliderBaseStylesType,
39+
};
40+
41+
describe('Slider - Mouse interactions', () => {
42+
it('Slider - Simple - when user hover slider, component controls the interaction', async () => {
43+
const setHover = jest.fn();
44+
const { getByRole } = renderProvider(
45+
<SliderStandAlone {...mockSliderStandAlone} setHover={setHover} />
46+
);
47+
const slider = getByRole(ROLES.SLIDER);
48+
await userEvent.hover(slider);
49+
expect(setHover).toHaveBeenCalledWith(true);
50+
await userEvent.unhover(slider);
51+
expect(setHover).toHaveBeenCalledWith(false);
52+
});
53+
it('Slider - Range - when user hover left slider, component controls the interaction', async () => {
54+
const setHover = jest.fn();
55+
const { getAllByRole } = renderProvider(
56+
<SliderStandAlone {...mockSliderStandAlone} range={true} setHover={setHover} />
57+
);
58+
const slider = getAllByRole(ROLES.SLIDER);
59+
await userEvent.hover(slider[0]);
60+
expect(setHover).toHaveBeenCalledWith(true);
61+
await userEvent.unhover(slider[0]);
62+
expect(setHover).toHaveBeenCalledWith(false);
63+
});
64+
it('Slider - Range - when user hover right slider, component controls the interaction', async () => {
65+
const setHover = jest.fn();
66+
const { getAllByRole } = renderProvider(
67+
<SliderStandAlone {...mockSliderStandAlone} range={true} setHover={setHover} />
68+
);
69+
const slider = getAllByRole(ROLES.SLIDER);
70+
await userEvent.hover(slider[1]);
71+
expect(setHover).toHaveBeenCalledWith(true);
72+
await userEvent.unhover(slider[1]);
73+
expect(setHover).toHaveBeenCalledWith(false);
74+
});
75+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './sliderHelperTextStandAlone';
2+
export * from './sliderScaleStandAlone';
3+
export * from './sliderThumbStandAlone';
4+
export * from './sliderButtonStandAlone';

0 commit comments

Comments
 (0)