Skip to content

Commit c311b77

Browse files
author
Kubit
committed
Improve pageControl component with icon props
1 parent d5ecc4d commit c311b77

13 files changed

+319
-64
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import '@testing-library/jest-dom/extend-expect';
2+
3+
import { fireEvent } from '@testing-library/react';
4+
import React from 'react';
5+
6+
import * as useMediaDevice from '@/hooks/useMediaDevice/useMediaDevice';
7+
import { renderProvider } from '@/tests/renderProvider/renderProvider.utility';
8+
import { windowMatchMedia } from '@/tests/windowMatchMedia/windowMatchMedia';
9+
import { DeviceBreakpointsType } from '@/types/breakpoints/breakpoints';
10+
11+
import { ButtonControlStandAlone } from '../components/buttonControlStandAlone';
12+
13+
describe('ButtonControlStandAlone', () => {
14+
afterEach(() => {
15+
jest.clearAllMocks();
16+
jest.resetAllMocks();
17+
jest.restoreAllMocks();
18+
});
19+
20+
beforeEach(() => {
21+
window.matchMedia = windowMatchMedia('onlyDesktop');
22+
jest
23+
.spyOn(useMediaDevice, 'useMediaDevice')
24+
.mockImplementation(() => DeviceBreakpointsType.DESKTOP);
25+
});
26+
27+
it('renders correctly with default props', () => {
28+
const { getByRole } = renderProvider(<ButtonControlStandAlone />);
29+
const button = getByRole('button');
30+
expect(button).toBeInTheDocument();
31+
expect(button).toHaveAttribute('type', 'button');
32+
expect(button).not.toBeDisabled();
33+
});
34+
35+
it('renders correctly with disabled prop', () => {
36+
const { getByRole } = renderProvider(<ButtonControlStandAlone disabled />);
37+
const button = getByRole('button');
38+
expect(button).toBeDisabled();
39+
});
40+
41+
it('passes aria props correctly', () => {
42+
const { getByRole } = renderProvider(<ButtonControlStandAlone aria-label="custom button" />);
43+
const button = getByRole('button');
44+
expect(button).toHaveAttribute('aria-label', 'custom button');
45+
});
46+
47+
it('handles click events correctly', () => {
48+
const handleClick = jest.fn();
49+
const { getByRole } = renderProvider(<ButtonControlStandAlone onClick={handleClick} />);
50+
const button = getByRole('button');
51+
fireEvent.click(button);
52+
expect(handleClick).toHaveBeenCalledTimes(1);
53+
});
54+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { IElementOrIcon } from '@/components/elementOrIcon/types/elementOrIcon';
2+
import { ICONS } from '@/designSystem/kubit/assets/icons/icons';
3+
4+
import { isIElementOrIcon } from '../helper/controlType';
5+
import { PageControlControlType } from '../types/pageControl';
6+
7+
describe('isIElementOrIcon', () => {
8+
it('should return true if control is of type IElementOrIcon', () => {
9+
const control: IElementOrIcon = { icon: 'some-icon' };
10+
expect(isIElementOrIcon(control)).toBe(true);
11+
});
12+
13+
it('should return false if control is not of type IElementOrIcon', () => {
14+
const control: PageControlControlType = { onClick: jest.fn() };
15+
expect(isIElementOrIcon(control)).toBe(false);
16+
});
17+
18+
it('should return false if control is undefined', () => {
19+
const control = undefined;
20+
expect(isIElementOrIcon(control)).toBe(false);
21+
});
22+
23+
it('should return false if control is an empty object', () => {
24+
const control = {};
25+
expect(isIElementOrIcon(control)).toBe(false);
26+
});
27+
28+
it('should return false if control has icon property as undefined', () => {
29+
const control: IElementOrIcon = { icon: undefined };
30+
expect(isIElementOrIcon(control)).toBe(false);
31+
});
32+
33+
it('should return true if control has icon property as a valid string', () => {
34+
const control: IElementOrIcon = { icon: ICONS.ICON_ALERT };
35+
expect(isIElementOrIcon(control)).toBe(true);
36+
});
37+
});

src/components/pageControl/__tests__/pageControl.test.tsx

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@ import React from 'react';
33

44
import { axe } from 'jest-axe';
55

6+
import * as useMediaDevice from '@/hooks/useMediaDevice/useMediaDevice';
67
import { renderProvider } from '@/tests/renderProvider/renderProvider.utility';
8+
import { windowMatchMedia } from '@/tests/windowMatchMedia/windowMatchMedia';
9+
import { DeviceBreakpointsType } from '@/types/breakpoints/breakpoints';
710

811
import { PageControl } from '../pageControl';
912

13+
const defaultMaxDots = 5;
14+
const dataTestId = 'PageControlComponet';
15+
1016
describe('PageControl tests', () => {
11-
const defaultMaxDots = 5;
12-
const dataTestId = 'PageControlComponet';
1317
it('Should render the correct dot number in LINE variant', async () => {
1418
const { container } = renderProvider(
1519
<PageControl
@@ -21,8 +25,8 @@ describe('PageControl tests', () => {
2125
/>
2226
);
2327
const controller = screen.getByTestId(dataTestId);
24-
const results = await axe(container);
2528

29+
const results = await axe(container);
2630
expect(container).toHTMLValidate();
2731
expect(results).toHaveNoViolations();
2832
expect(controller.children[0].childElementCount).toBe(4);
@@ -36,7 +40,6 @@ describe('PageControl tests', () => {
3640
variant: 'BULLETS',
3741
};
3842
const { rerender } = renderProvider(<PageControl {...commonProps} currentPosition={0} />);
39-
4043
const controller = screen.getByTestId(dataTestId);
4144

4245
expect(controller.children[0].childElementCount).toBe(defaultMaxDots + 1);
@@ -73,7 +76,6 @@ describe('PageControl tests', () => {
7376
/>
7477
);
7578
const controller = screen.getByTestId(dataTestId);
76-
7779
expect(controller.children[0].childElementCount).toBe(defaultMaxDots + 2);
7880
});
7981

@@ -85,21 +87,20 @@ describe('PageControl tests', () => {
8587
arrowsControlVariant="DEFAULT"
8688
currentPosition={4}
8789
dataTestId={dataTestId}
88-
leftArrowControl={{
90+
leftControl={{
8991
icon: 'UNICORN',
9092
['aria-label']: 'LEFT ARROW',
9193
onClick: handleLeftArrowControlClick,
9294
}}
9395
pages={7}
94-
rightArrowControl={{
96+
rightControl={{
9597
icon: 'UNICORN',
9698
['aria-label']: 'RIGHT ARROW',
9799
onClick: handleRightArrowControlClick,
98100
}}
99101
variant="BULLETS"
100102
/>
101103
);
102-
103104
const leftArrow = screen.getByRole('button', { name: 'LEFT ARROW' });
104105
const rightArrow = screen.getByRole('button', { name: 'RIGHT ARROW' });
105106

@@ -117,14 +118,14 @@ describe('PageControl tests', () => {
117118
arrowsControlVariant="DEFAULT"
118119
currentPosition={4}
119120
dataTestId={dataTestId}
120-
leftArrowControl={{
121+
leftControl={{
121122
icon: 'UNICORN',
122123
['aria-label']: 'LEFT ARROW',
123124
disabled: true,
124125
onClick: handleLeftArrowControlClick,
125126
}}
126127
pages={7}
127-
rightArrowControl={{
128+
rightControl={{
128129
icon: 'UNICORN',
129130
['aria-label']: 'RIGHT ARROW',
130131
disabled: true,
@@ -143,3 +144,47 @@ describe('PageControl tests', () => {
143144
expect(handleRightArrowControlClick).not.toHaveBeenCalledTimes(1);
144145
});
145146
});
147+
148+
describe('ButtonControl render', () => {
149+
afterEach(() => {
150+
jest.clearAllMocks();
151+
jest.resetAllMocks();
152+
jest.restoreAllMocks();
153+
});
154+
155+
beforeEach(() => {
156+
window.matchMedia = windowMatchMedia('onlyDesktop');
157+
jest
158+
.spyOn(useMediaDevice, 'useMediaDevice')
159+
.mockImplementation(() => DeviceBreakpointsType.DESKTOP);
160+
});
161+
162+
it('renders correctly with default props', async () => {
163+
const handleLeftArrowControlClick = jest.fn();
164+
const handleRightArrowControlClick = jest.fn();
165+
renderProvider(
166+
<PageControl
167+
arrowsControlVariant="DEFAULT"
168+
currentPosition={4}
169+
dataTestId={dataTestId}
170+
leftControl={{
171+
['aria-label']: 'LEFT ARROW',
172+
onClick: handleLeftArrowControlClick,
173+
}}
174+
pages={7}
175+
rightControl={{
176+
['aria-label']: 'RIGHT ARROW',
177+
onClick: handleRightArrowControlClick,
178+
}}
179+
variant="BULLETS"
180+
/>
181+
);
182+
const leftArrow = screen.getByRole('button', { name: 'LEFT ARROW' });
183+
const rightArrow = screen.getByRole('button', { name: 'RIGHT ARROW' });
184+
185+
await fireEvent.click(leftArrow);
186+
expect(handleLeftArrowControlClick).toHaveBeenCalled();
187+
await fireEvent.click(rightArrow);
188+
expect(handleRightArrowControlClick).toHaveBeenCalled();
189+
});
190+
});

src/components/pageControl/components/arrowControlStandAlone.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import React from 'react';
22

3+
import { IElementOrIcon } from '@/components/elementOrIcon/types/elementOrIcon';
4+
35
import { ElementOrIcon } from '../../elementOrIcon/elementOrIcon';
4-
import { PageControlArrowControlType } from '../types/pageControl';
5-
//types
66
import { ArrowsControlState } from '../types/pageControlStates';
77
import { ArrowsControlVariantStylesType } from '../types/pageControlTheme';
88

9-
interface IArrowControlStandAlone extends PageControlArrowControlType {
10-
arrowsControlStyles: ArrowsControlVariantStylesType;
9+
interface IArrowControlStandAlone extends IElementOrIcon {
10+
arrowsControlStyles?: ArrowsControlVariantStylesType;
1111
}
1212

1313
export const ArrowControlStandAlone = ({
@@ -16,9 +16,10 @@ export const ArrowControlStandAlone = ({
1616
...props
1717
}: IArrowControlStandAlone): JSX.Element => {
1818
const state = disabled ? ArrowsControlState.INACTIVE : ArrowsControlState.ACTIVE;
19+
1920
return (
2021
<ElementOrIcon
21-
customIconStyles={arrowsControlStyles[state]?.icon}
22+
customIconStyles={arrowsControlStyles?.[state]?.icon}
2223
disabled={disabled}
2324
{...props}
2425
/>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from 'react';
2+
3+
import { ButtonType } from '@/components/button/types/type';
4+
import { CommonStyleType } from '@/types/styles/commonStyle';
5+
import { pickAriaProps } from '@/utils/aria/aria';
6+
7+
import { ButtonControStyled } from '../pageControl.styled';
8+
import { ButtonControl } from '../types/pageControl';
9+
10+
interface IButtonControlStandAlone extends ButtonControl {
11+
buttonControlStyles?: CommonStyleType;
12+
dataTestId?: string;
13+
}
14+
15+
export const ButtonControlStandAlone = ({
16+
buttonControlStyles,
17+
disabled = false,
18+
...props
19+
}: IButtonControlStandAlone): JSX.Element => {
20+
const ariaProps = pickAriaProps(props);
21+
22+
return (
23+
<ButtonControStyled
24+
data-testid={props.dataTestId}
25+
disabled={disabled}
26+
styles={buttonControlStyles}
27+
type={ButtonType.BUTTON}
28+
{...props}
29+
{...ariaProps}
30+
/>
31+
);
32+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { IElementOrIcon } from '@/components/elementOrIcon/types/elementOrIcon';
2+
3+
import { PageControlControlType } from '../types/pageControl';
4+
5+
export const isIElementOrIcon = (control?: PageControlControlType): control is IElementOrIcon => {
6+
return (control as IElementOrIcon)?.icon !== undefined;
7+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './positions';
2+
export * from './controlType';

src/components/pageControl/pageControl.styled.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import styled from 'styled-components';
22

3+
import { CommonStyleType } from '@/types/styles/commonStyle';
4+
35
import { getStyles } from '../../utils/getStyles/getStyles';
46
// enums
57
import { PageControlState } from './types/pageControlStates';
@@ -36,8 +38,15 @@ export const LeftArrowControlWrapperStyled = styled.div<{
3638
`;
3739

3840
export const RightArrowControlWrapperStyled = styled.div<{
39-
arrowsControlStyles: ArrowsControlVariantStylesType;
41+
arrowsControlStyles?: ArrowsControlVariantStylesType;
42+
}>`
43+
line-height: 0;
44+
${({ arrowsControlStyles }) => getStyles(arrowsControlStyles?.rightArrowControlContainer)};
45+
`;
46+
47+
export const ButtonControStyled = styled.button<{
48+
styles?: CommonStyleType;
4049
}>`
4150
line-height: 0;
42-
${({ arrowsControlStyles }) => getStyles(arrowsControlStyles.rightArrowControlContainer)};
51+
${({ styles }) => getStyles(styles)};
4352
`;

0 commit comments

Comments
 (0)