Skip to content

Commit

Permalink
Update input buttons and input list component
Browse files Browse the repository at this point in the history
  • Loading branch information
hervedombya committed Dec 19, 2023
1 parent 6c5c5a3 commit ff085d8
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 27 deletions.
4 changes: 2 additions & 2 deletions src/lib/components/inputlist/InputButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const AddButton = ({
name={`addbtn${index}`}
id={`addbtn${index}`}
onClick={onClickFn}
aria-label="Add"
aria-label={`Add${index}`}
tooltip={{
overlay: 'Add',
placement: 'top',
Expand Down Expand Up @@ -97,7 +97,7 @@ export const SubButton = ({
variant="danger"
type="button"
disabled={isDisabled}
aria-label="Remove"
aria-label={`Remove${index}`}
name={`delbtn${index}`}
id={`delbtn${index}`}
onClick={() => deleteEntry(index)}
Expand Down
51 changes: 26 additions & 25 deletions src/lib/components/inputlist/InputList.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,24 @@ export type InputListProps<T> = HTMLProps<HTMLInputElement> & {

function InternalInputList<
T extends string | number | readonly string[] | undefined,
>({
onChange,
onBlur,
ref,
min,
max,
maxLength,
minLength,
pattern,
required,
disabled,
maxItems,
id,
value,
...rest
}: InputListProps<T>) {
>(
{
onChange,
onBlur,
min,
max,
maxLength,
minLength,
pattern,
required,
disabled,
maxItems,
value,
name,
...rest
}: InputListProps<T>,
_,
) {
const isMaxItemsReached =
maxItems !== undefined && maxItems !== null && value.length === maxItems;

Expand All @@ -47,13 +49,11 @@ function InternalInputList<
};

const deleteEntry = (entryIndex: number) => {
let tempValues = [...value];
tempValues.splice(entryIndex, 1);
if (tempValues.length === 0) {
tempValues = [''] as T[];
}
const newValues = value.filter((_, index) => index !== entryIndex);
const updatedValues = newValues.length === 0 ? ([''] as T[]) : newValues;

onChange?.({
target: { value: tempValues },
target: { value: updatedValues },
} as unknown as React.ChangeEvent<HTMLInputElement>);
};

Expand All @@ -62,7 +62,8 @@ function InternalInputList<
{value.map((val, index) => (
<Box display="flex" gap="0.25rem" alignItems="center" key={index}>
<Input
id={`${id}[${index}]`}
id={`${name}[${index}]`}
aria-label={`${name}${index}`}
inputSize={'1/2'}
value={val}
onChange={(evt) => {
Expand All @@ -76,14 +77,14 @@ function InternalInputList<
/>
<SubButton
index={index}
key={`${id}-delete-${value.join(',') + index}`}
key={`${name}-delete-${value.join(',') + index}`}
deleteEntry={deleteEntry}
items={value}
disabled={value.length === 1 && value[0] === ''}
/>
<AddButton
index={index}
key={`${id}-add-${value.join(',') + index}`}
key={`${name}-add-${value.join(',') + index}`}
insertEntry={insertEntry}
items={value}
disabled={val === '' || isMaxItemsReached}
Expand Down
102 changes: 102 additions & 0 deletions src/lib/components/inputlist/InputList.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { InputList, InputListProps } from './InputList.component';
import { FormSection } from '../form/Form.component';
import { QueryClient, QueryClientProvider } from 'react-query';

describe('InputList', () => {
const onChangeMock = jest.fn();

const renderInputList = (props: InputListProps<string[]>) => {
render(
<QueryClientProvider client={new QueryClient()}>
<FormSection>
<InputList
placeholder="Input list Test"
onChange={onChangeMock}
value={props.value}
name="inputListTest"
/>
</FormSection>
</QueryClientProvider>,
);
};

beforeEach(() => {
onChangeMock.mockClear();
});

it('should render an empty input list', () => {
renderInputList({
value: [''],
});

expect(screen.getByLabelText('inputListTest0')).toHaveValue('');
});

it('should render an input list with initial values', () => {
const initialValues = ['Value 1', 'Value 2', 'Value 3'];

renderInputList({
value: initialValues,
});

const inputElements = screen.getAllByRole('textbox');

expect(inputElements).toHaveLength(initialValues.length);

inputElements.forEach((input, index) => {
expect(input).toHaveValue(initialValues[index]);
});
});

it('should add a new input when clicking the add button', () => {
const initialValues = ['Value 1', 'Value 2'];

renderInputList({
value: initialValues,
});

const addButton = screen.getByLabelText('Add1');

fireEvent.click(addButton);

expect(onChangeMock).toHaveBeenCalledWith({
target: { value: [...initialValues, ''] },
});
});

it('should delete an input when clicking the delete button', () => {
const initialValues = ['Value 1', 'Value 2', 'Value 3'];

renderInputList({
value: initialValues,
});

const deleteButton = screen.getByLabelText('Remove1');

fireEvent.click(deleteButton);

expect(onChangeMock).toHaveBeenCalledWith({
target: { value: ['Value 1', 'Value 3'] },
});
});

it('should update the value of an input', () => {
const initialValues = ['Value 1', 'Value 2', 'Value 3'];

renderInputList({
value: initialValues,
});

const inputElements = screen.getAllByRole('textbox');

const newValue = 'New Value';

fireEvent.change(inputElements[1], { target: { value: newValue } });

expect(onChangeMock).toHaveBeenCalledWith({
target: { value: ['Value 1', newValue, 'Value 3'] },
});
});
});

0 comments on commit ff085d8

Please sign in to comment.