-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from kubit-ui/feature/improvements-and-fix-bugs
Feature/improvements and fix bugs
- Loading branch information
Showing
50 changed files
with
2,035 additions
and
344 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
165 changes: 165 additions & 0 deletions
165
src/components/pillSelectorV2/__tests__/pillSelector.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import { screen } from '@testing-library/react'; | ||
import * as React from 'react'; | ||
|
||
import { axe } from 'jest-axe'; | ||
|
||
import { ICONS } from '@/assets'; | ||
import { | ||
PillSelectorSizeTypeV2, | ||
PillSelectorVariantTypeV2, | ||
} from '@/designSystem/kubit/components/variants'; | ||
import { renderProvider } from '@/tests/renderProvider/renderProvider.utility'; | ||
import { ROLES } from '@/types'; | ||
|
||
import { PillSelectorControlled } from '../pillSelectorControlled'; | ||
import { PillSelectorUnControlled } from '../pillSelectorUnControlled'; | ||
import { IPillSelectorControlled, IPillSelectorUnControlled, PillSelectorType } from '../types'; | ||
|
||
const mockProps: IPillSelectorUnControlled = { | ||
variant: PillSelectorVariantTypeV2.DEFAULT, | ||
size: PillSelectorSizeTypeV2.LARGE, | ||
pills: [ | ||
{ label: { content: 'Pill 1' }, icon: { icon: ICONS.ICON_PLACEHOLDER }, value: 'value 1' }, | ||
{ label: { content: 'Pill 2 ' }, icon: { icon: ICONS.ICON_PLACEHOLDER }, value: 'value 2' }, | ||
{ label: { content: 'Pill 3' }, icon: { icon: ICONS.ICON_PLACEHOLDER }, value: 'value 3' }, | ||
{ label: { content: 'Pill 4' }, icon: { icon: ICONS.ICON_PLACEHOLDER }, value: 'value 4' }, | ||
], | ||
}; | ||
|
||
describe('PillSelectorUncontrolled', () => { | ||
it('Should render a set of pills, by default pill type is input checkbox (PillSelectorType.SELECTOR_MULTIPLE)', async () => { | ||
const { container } = renderProvider(<PillSelectorUnControlled {...mockProps} />); | ||
|
||
const pills = screen.getAllByRole(ROLES.CHECKBOX); | ||
expect(pills).toHaveLength(mockProps.pills?.length as number); | ||
|
||
const results = await axe(container); | ||
expect(container).toHTMLValidate(); | ||
expect(results).toHaveNoViolations(); | ||
}); | ||
|
||
it('When SELECTOR_SIMPLE, pills are render as checkbox', async () => { | ||
const { container } = renderProvider( | ||
<PillSelectorUnControlled {...mockProps} type={PillSelectorType.SELECTOR_SIMPLE} /> | ||
); | ||
|
||
const pills = screen.getAllByRole(ROLES.RADIO); | ||
expect(pills).toHaveLength(mockProps.pills?.length as number); | ||
|
||
const results = await axe(container); | ||
expect(container).toHTMLValidate(); | ||
expect(results).toHaveNoViolations(); | ||
}); | ||
|
||
it('Size prop is optional', () => { | ||
const { size, ...restMockProps } = mockProps; | ||
renderProvider(<PillSelectorUnControlled {...restMockProps} />); | ||
|
||
const pills = screen.getAllByRole(ROLES.CHECKBOX); | ||
expect(pills).toHaveLength(mockProps.pills?.length as number); | ||
}); | ||
|
||
it('When SELECTOR_MULTIPLE, value should be an array of the value of the selected options', () => { | ||
const value = [mockProps.pills?.[0].value as string]; | ||
renderProvider(<PillSelectorUnControlled {...mockProps} defaultValue={value} />); | ||
|
||
const pills = screen.getAllByRole(ROLES.CHECKBOX); | ||
expect(pills[0]).toBeChecked(); | ||
}); | ||
|
||
it('When SELECTOR_SIMPLE, value should be a value from the values of the selected options', () => { | ||
const value = mockProps.pills?.[0].value as string; | ||
renderProvider( | ||
<PillSelectorUnControlled | ||
{...mockProps} | ||
defaultValue={value} | ||
type={PillSelectorType.SELECTOR_SIMPLE} | ||
/> | ||
); | ||
|
||
const pills = screen.getAllByRole(ROLES.RADIO); | ||
expect(pills[0]).toBeChecked(); | ||
}); | ||
|
||
it('When SELECTOR_MULTIPLE, onChange should return an array of the value of the selected options', () => { | ||
const value = [mockProps.pills?.[0].value as string]; | ||
const handleChange = jest.fn(); | ||
renderProvider(<PillSelectorUnControlled {...mockProps} onChange={handleChange} />); | ||
|
||
const pills = screen.getAllByRole(ROLES.CHECKBOX); | ||
pills[0].click(); | ||
expect(handleChange).toHaveBeenCalledWith(value); | ||
}); | ||
|
||
it('When SELECTOR_MULTIPLE, onChange should return an array of the value of the selected options, if it is already selected it should be removed', () => { | ||
const value = [mockProps.pills?.[0].value as string]; | ||
const handleChange = jest.fn(); | ||
renderProvider( | ||
<PillSelectorUnControlled {...mockProps} defaultValue={value} onChange={handleChange} /> | ||
); | ||
|
||
const pills = screen.getAllByRole(ROLES.CHECKBOX); | ||
pills[0].click(); | ||
expect(handleChange).toHaveBeenCalledWith([]); | ||
}); | ||
|
||
it('When SELECTOR_MULTIPLE, onChange should return an array of the value of the selected options, if it not is already selected it should be added', () => { | ||
const value = [mockProps.pills?.[0].value as string]; | ||
const handleChange = jest.fn(); | ||
renderProvider( | ||
<PillSelectorUnControlled {...mockProps} defaultValue={value} onChange={handleChange} /> | ||
); | ||
|
||
const pills = screen.getAllByRole(ROLES.CHECKBOX); | ||
pills[1].click(); | ||
expect(handleChange).toHaveBeenCalledWith([ | ||
mockProps.pills?.[0].value as string, | ||
mockProps.pills?.[1].value as string, | ||
]); | ||
}); | ||
|
||
it('When SELECTOR_SIMPLE, onChange should return a value from the values of the selected options', () => { | ||
const value = mockProps.pills?.[0].value as string; | ||
const handleChange = jest.fn(); | ||
renderProvider( | ||
<PillSelectorUnControlled | ||
{...mockProps} | ||
type={PillSelectorType.SELECTOR_SIMPLE} | ||
onChange={handleChange} | ||
/> | ||
); | ||
|
||
const pills = screen.getAllByRole(ROLES.RADIO); | ||
pills[0].click(); | ||
expect(handleChange).toHaveBeenCalledWith(value); | ||
}); | ||
}); | ||
|
||
const mockPropsControlled: IPillSelectorControlled = { | ||
variant: PillSelectorVariantTypeV2.DEFAULT, | ||
size: PillSelectorSizeTypeV2.LARGE, | ||
pills: [ | ||
{ label: { content: 'Pill 1' }, icon: { icon: ICONS.ICON_PLACEHOLDER }, value: 'value 1' }, | ||
{ label: { content: 'Pill 2 ' }, icon: { icon: ICONS.ICON_PLACEHOLDER }, value: 'value 2' }, | ||
{ label: { content: 'Pill 3' }, icon: { icon: ICONS.ICON_PLACEHOLDER }, value: 'value 3' }, | ||
{ label: { content: 'Pill 4' }, icon: { icon: ICONS.ICON_PLACEHOLDER }, value: 'value 4' }, | ||
], | ||
}; | ||
|
||
describe('PillSelectorcontrolled', () => { | ||
it('Should render a set of pills, by default pill type is input checkbox (PillSelectorType.SELECTOR_MULTIPLE)', () => { | ||
renderProvider(<PillSelectorControlled {...mockPropsControlled} />); | ||
|
||
const pills = screen.getAllByRole(ROLES.CHECKBOX); | ||
expect(pills).toHaveLength(mockProps.pills?.length as number); | ||
}); | ||
|
||
it('If onChange is not passed, when pressing over a pill it will not trigger any action', () => { | ||
renderProvider(<PillSelectorControlled {...mockPropsControlled} />); | ||
|
||
const pills = screen.getAllByRole(ROLES.CHECKBOX); | ||
pills[0].click(); | ||
|
||
expect(pills[0]).not.toBeChecked(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export type { | ||
PillSelectorPillType as PillSelectorPillTypeV2, | ||
PillSelectorValueType as PillSelectorValueTypeV2, | ||
IPillSelectorUnControlled as IPillSelectorV2, | ||
IPillSelectorControlled as IPillSelectorControlledV2, | ||
PillSelectorPropsStylesType as PillSelectorPropsStylesTypeV2, | ||
PillSelectorStylesType as PillSelectorStylesTypeV2, | ||
} from './types'; | ||
|
||
export { PillSelectorType as PillSelectorTypeV2 } from './types/pillSelectorType'; | ||
|
||
export { PillSelectorUnControlled as PillSelectorV2 } from './pillSelectorUnControlled'; | ||
export { PillSelectorControlled as PillSelectorControlledV2 } from './pillSelectorControlled'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import styled from 'styled-components'; | ||
|
||
import { getStyles } from '@/utils'; | ||
|
||
import { PillSelectorPropsStylesType } from './types'; | ||
|
||
export const RootContainerStyled = styled.div<{ | ||
styles?: PillSelectorPropsStylesType; | ||
}>` | ||
${({ styles }) => getStyles(styles?.rootContainer)}; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import * as React from 'react'; | ||
|
||
import { STYLES_NAME } from '@/constants'; | ||
import { useStylesV2 } from '@/hooks'; | ||
|
||
import { PillSelectorStandAlone } from './pillSelectorStandAlone'; | ||
import { | ||
IPillSelectorControlled, | ||
PillSelectorType, | ||
PillSelectorVariantPropsStylesType, | ||
} from './types'; | ||
|
||
const PillSelectorControlledComponent = ( | ||
{ | ||
variant, | ||
size, | ||
ctv, | ||
type = PillSelectorType.SELECTOR_MULTIPLE, | ||
...props | ||
}: IPillSelectorControlled, | ||
ref: React.ForwardedRef<HTMLDivElement> | ||
) => { | ||
const variantStyles = useStylesV2<PillSelectorVariantPropsStylesType>({ | ||
styleName: STYLES_NAME.PILL_SELECTOR_V2, | ||
variantName: variant, | ||
customTokens: ctv, | ||
isOptional: true, | ||
}); | ||
|
||
// Size prop is optional, else select the first size from the variantStyles | ||
const styles = size ? variantStyles?.[size] : variantStyles?.[Object.keys(variantStyles)[0]]; | ||
|
||
const handlePillChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
if (!props.onChange) { | ||
return; | ||
} | ||
if (type === PillSelectorType.SELECTOR_SIMPLE) { | ||
props.onChange(event.target.value); | ||
return; | ||
} | ||
// SELECTOR MULTIPLE | ||
if (Array.isArray(props.value)) { | ||
const valueIncluded = props.value.includes(event.target.value); | ||
const newValue = valueIncluded | ||
? props.value.filter(v => v !== event.target.value) | ||
: [...props.value, event.target.value]; | ||
props.onChange(newValue); | ||
return; | ||
} | ||
// When value === undefined or value is not array | ||
props.onChange([event.target.value]); | ||
}; | ||
|
||
return ( | ||
<PillSelectorStandAlone | ||
ref={ref} | ||
styles={styles} | ||
type={type} | ||
onPillChange={handlePillChange} | ||
{...props} | ||
/> | ||
); | ||
}; | ||
|
||
export const PillSelectorControlled = React.forwardRef(PillSelectorControlledComponent); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import * as React from 'react'; | ||
|
||
import { PillTypeV2, PillV2 } from '@/components/pillV2'; | ||
|
||
import { RootContainerStyled } from './pillSelector.styled'; | ||
import { IPillSelectorStandAlone, PillSelectorType } from './types'; | ||
|
||
const PillSelectorStandAloneComponent = ( | ||
{ dataTestId = 'pillSelector', ...props }: IPillSelectorStandAlone, | ||
ref: React.ForwardedRef<HTMLDivElement> | undefined | null | ||
): JSX.Element => { | ||
return ( | ||
<RootContainerStyled ref={ref} styles={props.styles}> | ||
{props.pills?.map((pill, index) => { | ||
const selected = | ||
props.type === PillSelectorType.SELECTOR_MULTIPLE | ||
? pill.value !== undefined && | ||
Array.isArray(props.value) && | ||
props.value.includes(pill.value) | ||
: pill.value === props.value; | ||
return ( | ||
<PillV2 | ||
key={index} | ||
dataTestId={pill.dataTestId} | ||
disabled={pill.disabled ?? props.disabled} | ||
label={pill.label} | ||
leftIcon={pill.icon} | ||
name={props.name} | ||
rightIcon={selected ? props.selectedIcon : undefined} | ||
selected={selected} | ||
size={pill.size ?? props.styles?.pill?.size} | ||
type={ | ||
props.type === PillSelectorType.SELECTOR_MULTIPLE | ||
? PillTypeV2.SELECTOR_MULTIPLE | ||
: PillTypeV2.SELECTOR_SIMPLE | ||
} | ||
value={pill.value} | ||
variant={pill.variant ?? props.styles?.pill?.variant} | ||
onChange={props.onPillChange} | ||
/> | ||
); | ||
})} | ||
</RootContainerStyled> | ||
); | ||
}; | ||
|
||
export const PillSelectorStandAlone = React.forwardRef(PillSelectorStandAloneComponent); |
Oops, something went wrong.