Skip to content

Commit ea35228

Browse files
author
Hector Arce De Las Heras
committed
Improve Test Structure, Refine Button Component, and Enhance Loader Visibility
This commit focuses on improving the test structure, refining the button component, and enhancing the loader visibility in multiple components. Key changes include: Test cases for the button component in button.test.tsx have been restructured to use describe and test blocks, improving readability and organization. The disabled state of the button in button.styled.ts has been modified to account for the loading state. The button component in buttonStandAlone.tsx has been refined to handle the loading state more effectively. The loader's visibility in multiple files has been adjusted to be controlled by a visible prop rather than the loading prop. This change affects several components including LoaderStandAlone, LoadingIcon, and PopoverSearchListComponent. The input components in multiple files have been updated to accommodate the changes made to the loader's visibility. These updates include changes to the InputDropdown and InputSearch components. These changes improve the structure of tests, enhance the functionality of the button component, and provide more control over the visibility of the loader.
1 parent 4dff78f commit ea35228

30 files changed

+287
-168
lines changed

.storybook/manager-head.html

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,20 @@
66
src: url('./font/gtamericaregular.woff') format('truetype');
77
}
88

9+
@font-face {
10+
font-family: 'NunitoSans Font';
11+
font-weight: 400;
12+
src: url('./font/NunitoSans_10pt-Regular.ttf') format('truetype');
13+
}
14+
15+
@font-face {
16+
font-family: 'NunitoSans';
17+
font-weight: 700;
18+
src: url('./font/NunitoSans_10pt-Regular.ttf') format('truetype');
19+
}
20+
921
body {
10-
font-family: 'GTAmerica', sans-serif !important;
22+
font-family: 'NunitoSans', sans-serif !important;
1123
border-radius: 0 !important;
1224
}
1325

@@ -26,9 +38,9 @@
2638
.sidebar-item {
2739
padding-top: 0.5rem !important;
2840
padding-bottom: 0.5rem !important;
29-
font-size: 12px !important;
41+
font-size: 14px !important;
3042
font-style: normal !important;
31-
font-weight: 500 !important;
43+
font-weight: 400 !important;
3244
line-height: 16px;
3345
}
3446

src/components/button/__tests__/button.test.tsx

Lines changed: 74 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -51,102 +51,106 @@ const mockWithoutIcon = {
5151

5252
const children = 'Click me!';
5353

54-
test('Button component', async () => {
55-
const { container } = renderProvider(<Button {...mockProps}>{children}</Button>);
54+
describe('Button component', () => {
55+
test('Should render Button component', async () => {
56+
const { container } = renderProvider(<Button {...mockProps}>{children}</Button>);
5657

57-
const button = screen.getByRole('button', { name: /click/i });
58+
const button = screen.getByRole('button', { name: /click/i });
5859

59-
expect(button).toBeDefined();
60+
expect(button).toBeDefined();
6061

61-
const results = await axe(container);
62-
expect(container).toHTMLValidate();
63-
expect(results).toHaveNoViolations();
64-
});
62+
const results = await axe(container);
63+
expect(container).toHTMLValidate();
64+
expect(results).toHaveNoViolations();
65+
});
6566

66-
test('Button without variant nor state', async () => {
67-
const { container } = renderProvider(<Button {...mockPropsNoVariantNorState}>{children}</Button>);
67+
test('Button without variant nor state', async () => {
68+
const { container } = renderProvider(
69+
<Button {...mockPropsNoVariantNorState}>{children}</Button>
70+
);
6871

69-
const button = screen.getByRole('button', { name: /click/i });
72+
const button = screen.getByRole('button', { name: /click/i });
7073

71-
expect(button).toBeDefined();
74+
expect(button).toBeDefined();
7275

73-
const results = await axe(container);
74-
expect(container).toHTMLValidate();
75-
expect(results).toHaveNoViolations();
76-
});
76+
const results = await axe(container);
77+
expect(container).toHTMLValidate();
78+
expect(results).toHaveNoViolations();
79+
});
7780

78-
test('Button without type nor size', async () => {
79-
const { container } = renderProvider(<Button {...mockPropsNoTypeNorSize}>{children}</Button>);
81+
test('Button without type nor size', async () => {
82+
const { container } = renderProvider(<Button {...mockPropsNoTypeNorSize}>{children}</Button>);
8083

81-
const button = screen.getByRole('button', { name: /click/i });
84+
const button = screen.getByRole('button', { name: /click/i });
8285

83-
expect(button).toBeDefined();
86+
expect(button).toBeDefined();
8487

85-
const results = await axe(container);
86-
expect(container).toHTMLValidate();
87-
expect(results).toHaveNoViolations();
88-
});
88+
const results = await axe(container);
89+
expect(container).toHTMLValidate();
90+
expect(results).toHaveNoViolations();
91+
});
8992

90-
test('Button with loader', async () => {
91-
const { container } = renderProvider(<Button {...mockPropsLoader}>{children}</Button>);
93+
test('Button with loader', async () => {
94+
const { container } = renderProvider(<Button {...mockPropsLoader}>{children}</Button>);
9295

93-
const loader = screen.queryByText('loader');
96+
const loader = screen.queryByText('loader');
9497

95-
expect(loader).toBeDefined();
98+
expect(loader).toBeDefined();
9699

97-
const results = await axe(container);
98-
expect(container).toHTMLValidate();
99-
expect(results).toHaveNoViolations();
100-
});
100+
const results = await axe(container);
101+
expect(container).toHTMLValidate();
102+
expect(results).toHaveNoViolations();
103+
});
101104

102-
test('Button with loader as variant', async () => {
103-
const { queryByText, getByTestId, container } = renderProvider(
104-
<Button {...mockPropsLoaderAsVariant}>{children}</Button>
105-
);
105+
test('Button with loader as variant', async () => {
106+
const { queryByText, getByTestId, container } = renderProvider(
107+
<Button {...mockPropsLoaderAsVariant}>{children}</Button>
108+
);
106109

107-
// Should only render loader variant
108-
const loader = queryByText(mockPropsLoaderAsVariant.loader.variant);
109-
expect(loader).toBeNull();
110+
// Should only render loader variant
111+
const loader = queryByText(mockPropsLoaderAsVariant.loader.variant);
112+
expect(loader).toBeNull();
110113

111-
const loaderVariant = getByTestId('loaderStandaloneTestId');
112-
expect(loaderVariant).toBeDefined();
114+
const loaderVariant = getByTestId('loaderStandaloneTestId');
115+
expect(loaderVariant).toBeDefined();
113116

114-
const results = await axe(container);
115-
expect(container).toHTMLValidate();
116-
expect(results).toHaveNoViolations();
117-
});
117+
const results = await axe(container);
118+
expect(container).toHTMLValidate();
119+
expect(results).toHaveNoViolations();
120+
});
118121

119-
test('Button without icon', async () => {
120-
const { queryByRole, container } = renderProvider(
121-
<Button {...mockWithoutIcon}>{children}</Button>
122-
);
122+
test('Button without icon', async () => {
123+
const { queryByRole, container } = renderProvider(
124+
<Button {...mockWithoutIcon}>{children}</Button>
125+
);
123126

124-
expect(queryByRole('img')).toBeNull();
127+
expect(queryByRole('img')).toBeNull();
125128

126-
const results = await axe(container);
127-
expect(container).toHTMLValidate();
128-
expect(results).toHaveNoViolations();
129-
});
129+
const results = await axe(container);
130+
expect(container).toHTMLValidate();
131+
expect(results).toHaveNoViolations();
132+
});
130133

131-
test('Button without children and icon', async () => {
132-
const { container } = renderProvider(<Button {...mockWithoutIcon}></Button>);
134+
test('Button without children and icon', async () => {
135+
const { container } = renderProvider(<Button {...mockWithoutIcon}></Button>);
133136

134-
expect(container).toBeEmptyDOMElement();
137+
expect(container).toBeEmptyDOMElement();
135138

136-
const results = await axe(container);
137-
expect(container).toHTMLValidate();
138-
expect(results).toHaveNoViolations();
139-
});
139+
const results = await axe(container);
140+
expect(container).toHTMLValidate();
141+
expect(results).toHaveNoViolations();
142+
});
140143

141-
test('should render an SVG if icon prop is provided', async () => {
142-
const { container } = renderProvider(
143-
<Button icon={{ icon: 'icon', altText: 'altIcon' }} size="LARGE" variant="PRIMARY" />
144-
);
144+
test('should render an SVG if icon prop is provided', async () => {
145+
const { container } = renderProvider(
146+
<Button icon={{ icon: 'icon', altText: 'altIcon' }} size="LARGE" variant="PRIMARY" />
147+
);
145148

146-
const svg = screen.getByRole('img', { name: /altIcon/i });
149+
const svg = screen.getByRole('img', { name: /altIcon/i });
147150

148-
expect(svg).toBeInTheDocument();
149-
const results = await axe(container);
150-
expect(container).toHTMLValidate();
151-
expect(results).toHaveNoViolations();
151+
expect(svg).toBeInTheDocument();
152+
const results = await axe(container);
153+
expect(container).toHTMLValidate();
154+
expect(results).toHaveNoViolations();
155+
});
152156
});

src/components/button/button.styled.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,13 @@ export const ButtonStyled = styled.button<IButtonStyled>`
5858
${({ $state, $styles, $sizeStyles }) => setTokens($state, $styles, $sizeStyles)}
5959
6060
&:disabled {
61-
${({ $styles, $sizeStyles }) => setTokens(ButtonStateType.DISABLED, $styles, $sizeStyles)}
62-
cursor: 'default',
61+
cursor: default;
62+
${({ $styles, $sizeStyles, $loading }) =>
63+
setTokens(
64+
$loading ? ButtonStateType.LOADING : ButtonStateType.DISABLED,
65+
$styles,
66+
$sizeStyles
67+
)};
6368
}
6469
6570
&:hover:not(:disabled) {

src/components/button/buttonStandAlone.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@ export const ButtonStandAloneStructure = (props: IButtonStandAlone): JSX.Element
1515

1616
return (
1717
<>
18-
{props.loading && props.loader ? (
18+
{props.loader && (
1919
<>
2020
{typeof props.loader === 'object' && 'variant' in props.loader ? (
2121
<ButtonLoaderStyled>
22-
<Loader {...props.loader} width={getWidthSize()} />
22+
<Loader visible={props.loading} width={getWidthSize()} {...props.loader} />
2323
</ButtonLoaderStyled>
2424
) : (
2525
<ButtonLoaderStyled>{props.loader as React.ReactNode}</ButtonLoaderStyled>
2626
)}
2727
</>
28-
) : (
28+
)}
29+
{!props.loading && (
2930
<>
3031
<ElementOrIcon
3132
linearIcon
@@ -34,7 +35,6 @@ export const ButtonStandAloneStructure = (props: IButtonStandAlone): JSX.Element
3435
width={getWidthSize()}
3536
{...props.icon}
3637
/>
37-
3838
{props.children}
3939
</>
4040
)}
@@ -47,6 +47,8 @@ const ButtonStandAloneComponent = (
4747
ref: React.ForwardedRef<HTMLButtonElement> | undefined | null
4848
): JSX.Element => {
4949
const ariaProps = pickAriaProps(props);
50+
const disabled =
51+
props.state === ButtonStateType.DISABLED || props.state === ButtonStateType.LOADING;
5052

5153
return (
5254
<ButtonStyled
@@ -65,7 +67,7 @@ const ButtonStandAloneComponent = (
6567
$styles={props.styles}
6668
alignText={props.alignText}
6769
data-testid={props.dataTestId}
68-
disabled={props.state === ButtonStateType.DISABLED}
70+
disabled={disabled}
6971
form={props.form}
7072
minWidth={props.minWidth}
7173
tabIndex={props.tabIndex}

src/components/dropdownSelected/dropdownSelectedStandAlone.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ import { IDropdownSelectedStandAlone } from './types';
2222

2323
const DROPDOWN_SELECTED_BASE_ID = 'DropdownSelected';
2424

25-
const DropdownSelectedStandAloneComponent = (props: IDropdownSelectedStandAlone): JSX.Element => {
25+
const DropdownSelectedStandAloneComponent = (
26+
props: IDropdownSelectedStandAlone,
27+
ref: React.ForwardedRef<HTMLDivElement> | undefined | null
28+
): JSX.Element => {
2629
const BASE_ID = useId(DROPDOWN_SELECTED_BASE_ID);
2730
const POPOVER_ID = `${BASE_ID}-popover`;
2831
const ariaControls = props.open ? `${BASE_ID}-list` : undefined;
@@ -65,6 +68,7 @@ const DropdownSelectedStandAloneComponent = (props: IDropdownSelectedStandAlone)
6568

6669
return (
6770
<DropdrownSelectedContainerStyled
71+
ref={ref}
6872
data-testid={props.dataTestIdComponent}
6973
styles={props.styles}
7074
onBlur={event => props.onFocus?.(event)}

src/components/input/components/loader.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ import { Loader } from '@/components/loader';
66
import { LoaderWrapperStyled } from '../input.styled';
77
import { IInputLoader } from '../types/input';
88

9-
export const LoaderStandAlone = (props: IInputLoader): JSX.Element | null => {
10-
if (!props.loading || !(props.styles?.loaderVariant || props.loader?.variant)) {
11-
return null;
12-
}
9+
export const LoaderStandAlone = (props: IInputLoader): JSX.Element => {
1310
return (
1411
<LoaderWrapperStyled styles={props.styles}>
1512
<Loader
1613
variant={props.styles?.loaderVariant}
14+
visible={props.loading}
1715
width={props.styles?.loaderIcon?.width}
1816
{...props.loader}
1917
/>

src/components/input/inputStandAlone.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ const InputStandAloneComponent = (
117117
: undefined
118118
}
119119
disabled={isDisabled(state)}
120-
icon={props.icon}
120+
icon={{ dataTestId: `${props.dataTestId}Icon`, ...props.icon }}
121121
iconPosition={props.iconPosition}
122122
loading={props.loading}
123123
state={state}

src/components/input/stories/input.stories.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ const commonArgs: IInputUnControlled = {
5151
icon: { icon: ICONS.ICON_PLACEHOLDER },
5252
secondaryLabel: labelSecondary(themeSelected),
5353
additionalInfo: additionalInfoAction(themeSelected),
54+
loader: {
55+
variant: Object.values(variantsObject[themeSelected].LoaderVariantType || {})[0] as string,
56+
altText: 'loaderAltText',
57+
},
5458
};
5559

5660
export const Input: Story = {

src/components/input/types/inputStyledPropsType.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export type TextCounterStyledProps = {
3434
};
3535

3636
export type LoaderStyledProps = {
37+
loading?: boolean;
3738
styles?: InputStateProps;
3839
};
3940

src/components/inputDropdown/__tests__/inputDropdown.test.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,17 +150,26 @@ describe('New Input Dropdown Component', () => {
150150
});
151151

152152
it('Should render loading and valueSelected', async () => {
153+
renderProvider(
154+
<InputDropdown {...mockProps} loader={{ altText: 'loading' }} loadingList={true} />
155+
);
156+
157+
const inputDropdownLoading = screen.getByText('loading');
158+
expect(inputDropdownLoading).toBeInTheDocument();
159+
});
160+
161+
it('Should render loading text and loading icon when options list is empty', async () => {
153162
renderProvider(
154163
<InputDropdown
155164
{...mockProps}
156-
loader={{ altText: 'loading' }}
157165
loadingList={true}
166+
loadingText={{ content: 'loading' }}
158167
optionList={{ options: [] }}
159168
/>
160169
);
161170

162-
const inputDropdownLoading = screen.getByLabelText('loading');
163-
expect(inputDropdownLoading).toBeInTheDocument();
171+
const inputSearchLoading = screen.getByText('loading');
172+
expect(inputSearchLoading).toBeInTheDocument();
164173
});
165174

166175
it('Should allow select an option', async () => {

0 commit comments

Comments
 (0)