diff --git a/src/form/components/EditableList2/EditableList2.test.js b/src/form/components/EditableList2/EditableList2.test.js index 6d82fb90..b06fb819 100644 --- a/src/form/components/EditableList2/EditableList2.test.js +++ b/src/form/components/EditableList2/EditableList2.test.js @@ -1,7 +1,157 @@ +import React, { useState } from 'react'; +import Input2 from '../Input2'; import EditableList2 from './index'; +function isRequired(value) { + return value ? '' : 'Field is required'; +} + +function Component(props) { + const [value, setValue] = useState([]); + + return ( + + ); +} + +const selectors = { + wrapper: '.editable-list__wrapper', + header: '.editable-list__header', + addButton: '.editable-list__header .tyk-button', + list: '.editable-list__list', + listItem: '.editable-list__item', + errorMessage: '.tyk-form-control__error-message', + itemDeleteButton: '.editable-list__item .tyk-button', +}; + describe('EditableList2', () => { - it('TODO', () => { - expect(true).to.equal(true); + it('renders the component', () => { + cy.mount(); + + cy.get(selectors.wrapper) + .should('exist') + .get(selectors.header) + .should('exist'); + }); + + it('does not render the list by default if it is empty, unless hideOnEmpty is set to false', () => { + cy.mount() + .get(selectors.list) + .should('not.exist'); + + cy.mount() + .get(selectors.list) + .should('exist') + .get(selectors.listItem) + .should('have.length', 1); + }); + + it('clicking on the add button adds a new row', () => { + cy.mount() + .get(selectors.listItem) + .should('have.length', 1); // the header + + cy.get(selectors.addButton) + .click(); + + cy.get(selectors.listItem) + .should('have.length', 2); // header + 1 row + }); + + it('clicking on the add button two times triggers validation', () => { + cy.mount() + .get(selectors.addButton) + .click(); + + cy.get(selectors.errorMessage) + .should('not.exist'); + + cy.get(selectors.addButton) + .click(); + + cy.get(selectors.errorMessage) + .should('exist'); + + cy.get(selectors.listItem) + .find('input') + .type('anything'); + + cy.get(selectors.errorMessage) + .should('not.exist'); + }); + + it('we can add multiple rows (if we pass validations)', () => { + cy.mount() + .get(selectors.addButton) + .click(); + + cy.get(selectors.listItem) + .find('input') + .type('anything'); + + cy.get(selectors.addButton) + .click(); + + cy.get(selectors.listItem) + .should('have.length', 3); // 1 header + 2 list items + }); + + it('we can remove rows by clicking on the item\'s remove icon', () => { + cy.mount() + .get(selectors.addButton) + .click(); + + cy.get(selectors.listItem) + .should('have.length', 2); // 1 header + 1 list item + + cy.get(selectors.itemDeleteButton) + .click(); + + cy.get(selectors.listItem) + .should('have.length', 1); // 1 header + 0 list items + }); + + it('can render with an error', () => { + cy.mount(); + + cy.get(selectors.errorMessage) + .should('exist'); + }); + + it('can render in a disabled state', () => { + cy.mount(); + + cy.get(selectors.addButton) + .should('not.exist'); + + cy.get(selectors.listItem) + .find('input') + .should('have.attr', 'disabled'); + + cy.get(selectors.itemDeleteButton) + .should('have.class', 'disabled'); }); }); diff --git a/src/form/components/EditableList2/FieldsList.js b/src/form/components/EditableList2/FieldsList.js index 9200db4c..7a9fcd46 100644 --- a/src/form/components/EditableList2/FieldsList.js +++ b/src/form/components/EditableList2/FieldsList.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import Button from '../../../components/Button'; -const FieldsList = ({ +function FieldsList({ fields, disabled, readOnly, @@ -12,40 +12,45 @@ const FieldsList = ({ onDelete, value, rowIndex, -}) => ( -
  • - { - components.map((Component, index) => { - let field = fields[index]; - let tempField = typeof field === 'function' ? field(rowIndex, index) : field; - return ( - /* eslint-disable-next-line */ -
    - -
    - ); - }) - } -
    -
    -
  • -); +}) { + return ( +
  • + { + components.map((Component, index) => { + const field = fields[index]; + const tempField = typeof field === 'function' ? field(rowIndex, index) : field; + return ( +
    + +
    + ); + }) + } +
    +
    +
  • + ); +} FieldsList.propTypes = { disabled: PropTypes.bool, diff --git a/src/form/components/EditableList2/ListHeader.js b/src/form/components/EditableList2/ListHeader.js index be71c84e..f318d91a 100644 --- a/src/form/components/EditableList2/ListHeader.js +++ b/src/form/components/EditableList2/ListHeader.js @@ -1,19 +1,26 @@ import React from 'react'; import PropTypes from 'prop-types'; -const ListHeader = ({ +function ListHeader({ fields, readOnly, -}) => ( -
  • - { - fields.map(field => ( -
    {field?.props?.label}
    - )) - } -
    Delete
    -
  • -); +}) { + return ( +
  • + { + fields.map((field) => ( +
    + {field?.props?.label} +
    + )) + } +
    Delete
    +
  • + ); +} ListHeader.propTypes = { fields: PropTypes.instanceOf(Array), diff --git a/src/form/components/EditableList2/Readme.md b/src/form/components/EditableList2/Readme.md index 3d7f7ee5..3811090d 100644 --- a/src/form/components/EditableList2/Readme.md +++ b/src/form/components/EditableList2/Readme.md @@ -34,7 +34,7 @@ placeholder: 'Enter claim name', value: '', validate: isRequired - } + } }, { component: Input2, @@ -49,7 +49,7 @@ placeholder: 'Add Policy', value: '', validate: isRequired - } + } } ]} /> @@ -98,7 +98,7 @@ validateOnChange: (values, lastValue) => {console.log(lastValue, !isNaN(lastValue.id)); return !isNaN(lastValue.id) ? undefined : 'Added value is not a number'}, validate: formikRequired('This field is required') }); - + useEffect(() => { setTimeout(() => { @@ -134,7 +134,7 @@ theme: 'default rounded-corners', placeholder: 'Enter claim name', validate: formikRequired('This field is required') - } + } }), { component: Combobox2, @@ -170,7 +170,7 @@ label: 'Claim name', theme: 'default rounded-corners', placeholder: 'Enter claim name', - } + } }, { component: Input2, @@ -183,7 +183,7 @@ label: 'Policy', theme: 'default rounded-corners', placeholder: 'Add Policy', - } + } } ]} /> @@ -238,7 +238,7 @@ label: 'Claim name', theme: 'default rounded-corners', placeholder: 'Enter claim name', - } + } }, { component: Combobox2, @@ -252,7 +252,7 @@ tagSeparators: [' ', 'Enter', ':', '@'], name: "combobox", theme: "default rounded-corners", - } + } } ]} /> diff --git a/src/form/components/EditableList2/index.js b/src/form/components/EditableList2/index.js index a535e515..5d243eb4 100644 --- a/src/form/components/EditableList2/index.js +++ b/src/form/components/EditableList2/index.js @@ -15,7 +15,7 @@ const getUID = prefix => `${prefix}-${id++}`; * Editable list is a component, that lists rows of form elements (can have n elements on a row), * and stores the values of all the rows in an Array list */ -const EditableList2 = ({ +function EditableList2({ addButtonName, disabled, readOnly, @@ -26,7 +26,7 @@ const EditableList2 = ({ onChange = () => {}, hideOnEmpty = true, wrapperClassName = '', -}) => { +}) { const [internalErrors, setInteranlErrors] = useState(null); const updateRowValue = (rowIndex, fieldIndex, componentValue, isValid) => { @@ -52,13 +52,13 @@ const EditableList2 = ({ onChange(tempValueArr); }; - const hasErrors = errors => Boolean(errors?.flat()?.filter(Boolean).length); + const hasErrors = (errors) => Boolean(errors?.flat()?.filter(Boolean).length); const Components = useMemo( - () => fields.map(field => { - let tempField = typeof field === 'function' ? field() : field; + () => fields.map((field) => { + const tempField = typeof field === 'function' ? field() : field; - return withValidation(tempField?.component || <>) + return withValidation(tempField?.component || null); }), [], ); @@ -101,23 +101,21 @@ const EditableList2 = ({ {value?.length || !hideOnEmpty ? (
      {(value || [[]]).map((v, i) => ( - <> - - + ))}
    @@ -127,7 +125,7 @@ const EditableList2 = ({ ) : null} ); -}; +} EditableList2.propTypes = { /** Sets Editable list in edit mode. diff --git a/src/form/components/EditableList2/validate-values.js b/src/form/components/EditableList2/validate-values.js index 33f59845..c2e494eb 100644 --- a/src/form/components/EditableList2/validate-values.js +++ b/src/form/components/EditableList2/validate-values.js @@ -1,5 +1,5 @@ const validateValues = (fields, rowValues) => (rowValues || [[undefined, undefined]])?.map( - colValue => colValue?.map( + (colValue) => colValue?.map( (value, index) => fields?.[index]?.props?.validate && fields[index].props.validate(value), ), diff --git a/src/index.js b/src/index.js index 1e43f367..ab446c84 100644 --- a/src/index.js +++ b/src/index.js @@ -55,7 +55,6 @@ export { default as Pagination } from './form/components/Pagination'; export { default as StringBuilder } from './form/components/StringBuilder'; // -- Formik - export { default as FormikCheckbox } from './form/formik/FormikCheckbox'; export { default as FormikCodeEditor } from './form/formik/FormikCodeEditor'; export { default as FormikCombobox } from './form/formik/FormikCombobox'; @@ -76,7 +75,6 @@ export { default as FormikStringBuilder } from './form/formik/FormikStringBuilde export { default as FormikWrapper } from './utils/formik'; // Redux - Form - export { default as FieldCodeEditor } from './form/redux-form/FieldCodeEditor'; export { default as FieldCombobox } from './form/redux-form/FieldCombobox'; export { default as FieldDropdown } from './form/redux-form/FieldDropdown';