Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests for the editable list component #355

Merged
merged 1 commit into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 152 additions & 2 deletions src/form/components/EditableList2/EditableList2.test.js
Original file line number Diff line number Diff line change
@@ -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 (
<EditableList2
onChange={setValue}
value={value}
label="Map Something to Something Else"
addButtonName="Add Row"
fields={[
{
component: Input2,
styles: {
width: '200px',
},
size: 4,
props: {
name: 'input',
label: 'Something',
theme: 'default rounded-corners',
placeholder: 'Enter claim name',
value: '',
validate: isRequired,
},
},
]}
{...props}
/>
);
}

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(<Component />);

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(<Component />)
.get(selectors.list)
.should('not.exist');

cy.mount(<Component hideOnEmpty={false} />)
.get(selectors.list)
.should('exist')
.get(selectors.listItem)
.should('have.length', 1);
});

it('clicking on the add button adds a new row', () => {
cy.mount(<Component hideOnEmpty={false} />)
.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(<Component hideOnEmpty={false} />)
.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(<Component hideOnEmpty={false} />)
.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(<Component hideOnEmpty={false} />)
.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(<Component error="something went wrong" />);

cy.get(selectors.errorMessage)
.should('exist');
});

it('can render in a disabled state', () => {
cy.mount(<Component disabled hideOnEmpty={false} value={[['foo', 'row-1']]} />);

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');
});
});
75 changes: 40 additions & 35 deletions src/form/components/EditableList2/FieldsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -12,40 +12,45 @@ const FieldsList = ({
onDelete,
value,
rowIndex,
}) => (
<li className="editable-list__item">
{
components.map((Component, index) => {
let field = fields[index];
let tempField = typeof field === 'function' ? field(rowIndex, index) : field;
return (
/* eslint-disable-next-line */
<div className={`editable-list__item-cell editable-list__item--size-${fields[index]?.size || 12}`}>
<Component
{...tempField?.props}
label=""
value={value[index]}
/* eslint-disable-next-line */
onChange={onChange.bind(null, index)}
error={errors?.[index]}
disabled={disabled || tempField?.props?.disabled}
readOnly={readOnly || tempField?.props?.readOnly}
/>
</div>
);
})
}
<div className={`editable-list__item-cell editable-list__item-action ${readOnly && 'editable-list__item-action--read-only'}`}>
<Button
iconOnly
iconType="trash-alt"
theme="primary-link"
onClick={onDelete}
disabled={readOnly || disabled}
/>
</div>
</li>
);
}) {
return (
<li className="editable-list__item">
{
components.map((Component, index) => {
const field = fields[index];
const tempField = typeof field === 'function' ? field(rowIndex, index) : field;
return (
<div
/* eslint-disable-next-line react/no-array-index-key */
key={`${rowIndex}-${index}`}
className={`editable-list__item-cell editable-list__item--size-${fields[index]?.size || 12}`}
>
<Component
{...tempField?.props}
label=""
value={value[index]}
/* eslint-disable-next-line */
onChange={onChange.bind(null, index)}
error={errors?.[index]}
disabled={disabled || tempField?.props?.disabled}
readOnly={readOnly || tempField?.props?.readOnly}
/>
</div>
);
})
}
<div className={`editable-list__item-cell editable-list__item-action ${readOnly && 'editable-list__item-action--read-only'}`}>
<Button
iconOnly
iconType="trash-alt"
theme="primary-link"
onClick={onDelete}
disabled={readOnly || disabled}
/>
</div>
</li>
);
}

FieldsList.propTypes = {
disabled: PropTypes.bool,
Expand Down
29 changes: 18 additions & 11 deletions src/form/components/EditableList2/ListHeader.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import React from 'react';
import PropTypes from 'prop-types';

const ListHeader = ({
function ListHeader({
fields,
readOnly,
}) => (
<li className="editable-list__item editable-list__item-header">
{
fields.map(field => (
<div className={`editable-list__item-cell editable-list__item--size-${field?.size || 12}`}>{field?.props?.label}</div>
))
}
<div className={`editable-list__item-cell editable-list__item-action ${readOnly && 'editable-list__item-action--read-only'}`}>Delete</div>
</li>
);
}) {
return (
<li className="editable-list__item editable-list__item-header">
{
fields.map((field) => (
<div
key={field?.props?.label || JSON.stringify(field)}
className={`editable-list__item-cell editable-list__item--size-${field?.size || 12}`}
>
{field?.props?.label}
</div>
))
}
<div className={`editable-list__item-cell editable-list__item-action ${readOnly && 'editable-list__item-action--read-only'}`}>Delete</div>
</li>
);
}

ListHeader.propTypes = {
fields: PropTypes.instanceOf(Array),
Expand Down
16 changes: 8 additions & 8 deletions src/form/components/EditableList2/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
placeholder: 'Enter claim name',
value: '',
validate: isRequired
}
}
},
{
component: Input2,
Expand All @@ -49,7 +49,7 @@
placeholder: 'Add Policy',
value: '',
validate: isRequired
}
}
}
]}
/>
Expand Down Expand Up @@ -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(() => {
Expand Down Expand Up @@ -134,7 +134,7 @@
theme: 'default rounded-corners',
placeholder: 'Enter claim name',
validate: formikRequired('This field is required')
}
}
}),
{
component: Combobox2,
Expand Down Expand Up @@ -170,7 +170,7 @@
label: 'Claim name',
theme: 'default rounded-corners',
placeholder: 'Enter claim name',
}
}
},
{
component: Input2,
Expand All @@ -183,7 +183,7 @@
label: 'Policy',
theme: 'default rounded-corners',
placeholder: 'Add Policy',
}
}
}
]}
/>
Expand Down Expand Up @@ -238,7 +238,7 @@
label: 'Claim name',
theme: 'default rounded-corners',
placeholder: 'Enter claim name',
}
}
},
{
component: Combobox2,
Expand All @@ -252,7 +252,7 @@
tagSeparators: [' ', 'Enter', ':', '@'],
name: "combobox",
theme: "default rounded-corners",
}
}
}
]}
/>
Expand Down
Loading
Loading