1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-22 09:23:21 +01:00

Continue converting tests from enzyme to @testing-library/react. (#15941)

This commit is contained in:
Thomas Huang 2022-09-23 07:41:35 -07:00 committed by GitHub
parent 9efdf87e86
commit aff2d82bb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 660 additions and 460 deletions

View File

@ -0,0 +1,216 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CurrencyInput Component rendering should render properly with a fiat value 1`] = `
<div>
<div
class="unit-input"
>
<div
class="unit-input__inputs"
>
<div
class="unit-input__input-container"
>
<input
class="unit-input__input"
data-testid="currency-input"
dir="ltr"
placeholder="0"
style="width: 1.5ch;"
type="number"
value="1"
/>
<div
class="unit-input__suffix"
>
USD
</div>
</div>
<div
class="currency-display-component currency-input__conversion-component"
title="0.00432788 ETH"
>
<span
class="currency-display-component__prefix"
/>
<span
class="currency-display-component__text"
>
0.00432788
</span>
<span
class="currency-display-component__suffix"
>
ETH
</span>
</div>
</div>
<button
class="currency-input__swap-component"
data-testid="currency-swap"
>
<i
class="fa fa-retweet fa-lg"
/>
</button>
</div>
</div>
`;
exports[`CurrencyInput Component rendering should render properly with a native value when hideSecondary is true 1`] = `
<div>
<div
class="unit-input"
>
<div
class="unit-input__inputs"
>
<div
class="unit-input__input-container"
>
<input
class="unit-input__input"
data-testid="currency-input"
dir="ltr"
placeholder="0"
style="width: 10ch;"
type="number"
value="0.00432788"
/>
<div
class="unit-input__suffix"
>
ETH
</div>
</div>
<div
class="currency-input__conversion-component"
>
No conversion rate available
</div>
</div>
<button
class="currency-input__swap-component"
data-testid="currency-swap"
>
<i
class="fa fa-retweet fa-lg"
/>
</button>
</div>
</div>
`;
exports[`CurrencyInput Component rendering should render properly with an ETH value 1`] = `
<div>
<div
class="unit-input"
>
<div
class="unit-input__inputs"
>
<div
class="unit-input__input-container"
>
<input
class="unit-input__input"
data-testid="currency-input"
dir="ltr"
placeholder="0"
style="width: 1.5ch;"
type="number"
value="1"
/>
<div
class="unit-input__suffix"
>
ETH
</div>
</div>
<div
class="currency-display-component currency-input__conversion-component"
title="$231.06 USD"
>
<span
class="currency-display-component__prefix"
/>
<span
class="currency-display-component__text"
>
$231.06
</span>
<span
class="currency-display-component__suffix"
>
USD
</span>
</div>
</div>
<button
class="currency-input__swap-component"
data-testid="currency-swap"
>
<i
class="fa fa-retweet fa-lg"
/>
</button>
</div>
</div>
`;
exports[`CurrencyInput Component rendering should render properly without a suffix 1`] = `
<div>
<div
class="unit-input"
>
<div
class="unit-input__inputs"
>
<div
class="unit-input__input-container"
>
<input
class="unit-input__input"
data-testid="currency-input"
dir="ltr"
placeholder="0"
style="width: 1.5ch;"
type="number"
value="0"
/>
<div
class="unit-input__suffix"
>
ETH
</div>
</div>
<div
class="currency-display-component currency-input__conversion-component"
title="$0.00 USD"
>
<span
class="currency-display-component__prefix"
/>
<span
class="currency-display-component__text"
>
$0.00
</span>
<span
class="currency-display-component__suffix"
>
USD
</span>
</div>
</div>
<button
class="currency-input__swap-component"
data-testid="currency-swap"
>
<i
class="fa fa-retweet fa-lg"
/>
</button>
</div>
</div>
`;

View File

@ -146,11 +146,16 @@ export default function CurrencyInput({
onChange,
onPreferenceToggle,
}}
dataTestId="currency-input"
suffix={shouldUseFiat ? secondarySuffix : primarySuffix}
onChange={handleChange}
value={initialDecimalValue}
actionComponent={
<button className="currency-input__swap-component" onClick={swap}>
<button
className="currency-input__swap-component"
data-testid="currency-swap"
onClick={swap}
>
<i className="fa fa-retweet fa-lg" />
</button>
}

View File

@ -1,344 +1,160 @@
import React from 'react';
import PropTypes from 'prop-types';
import { mount } from 'enzyme';
import sinon from 'sinon';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import UnitInput from '../../ui/unit-input';
import CurrencyDisplay from '../../ui/currency-display';
import CurrencyInput from './currency-input';
import { fireEvent, waitFor } from '@testing-library/react';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import CurrencyInput from '.';
describe('CurrencyInput Component', () => {
const mockStore = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
preferences: {
showFiatInTestnets: true,
},
},
};
describe('rendering', () => {
it('should render properly without a suffix', () => {
const mockStore = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
preferences: {
showFiatInTestnets: true,
},
},
};
const store = configureMockStore()(mockStore);
const wrapper = mount(
<Provider store={store}>
<CurrencyInput />
</Provider>,
);
expect(wrapper).toHaveLength(1);
expect(wrapper.find(UnitInput)).toHaveLength(1);
});
it('should render properly with a suffix', () => {
const mockStore = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
preferences: {
showFiatInTestnets: true,
},
},
};
const store = configureMockStore()(mockStore);
const wrapper = mount(
<Provider store={store}>
<CurrencyInput />
</Provider>,
);
const { container } = renderWithProvider(<CurrencyInput />, store);
expect(wrapper).toHaveLength(1);
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('ETH');
expect(wrapper.find(CurrencyDisplay)).toHaveLength(1);
expect(container).toMatchSnapshot();
});
it('should render properly with an ETH value', () => {
const mockStore = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
preferences: {
showFiatInTestnets: true,
},
},
};
const store = configureMockStore()(mockStore);
const wrapper = mount(
<Provider store={store}>
<CurrencyInput hexValue="de0b6b3a7640000" />
</Provider>,
const props = {
hexValue: 'de0b6b3a7640000',
};
const { container } = renderWithProvider(
<CurrencyInput {...props} />,
store,
);
expect(wrapper).toHaveLength(1);
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('ETH');
expect(wrapper.find('.unit-input__input').props().value).toStrictEqual(1);
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
'$231.06USD',
);
expect(container).toMatchSnapshot();
});
it('should render properly with a fiat value', () => {
const mockStore = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
preferences: {
showFiatInTestnets: true,
},
},
};
const store = configureMockStore()(mockStore);
const handleChangeSpy = sinon.spy();
const wrapper = mount(
<Provider store={store}>
<CurrencyInput
onChange={handleChangeSpy}
hexValue="f602f2234d0ea"
featureSecondary
/>
</Provider>,
const props = {
onChange: jest.fn(),
hexValue: 'f602f2234d0ea',
featureSecondary: true,
};
const { container } = renderWithProvider(
<CurrencyInput {...props} />,
store,
);
expect(wrapper).toHaveLength(1);
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('USD');
expect(wrapper.find('.unit-input__input').props().value).toStrictEqual(1);
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
'0.00432788ETH',
);
expect(container).toMatchSnapshot();
});
it('should render properly with a native value when hideSecondary is true', () => {
const mockStore = {
const hideSecondaryState = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
...mockStore.metamask,
preferences: {
showFiatInTestnets: false,
},
hideSecondary: true,
},
hideSecondary: true,
};
const store = configureMockStore()(mockStore);
const handleChangeSpy = sinon.spy();
const wrapper = mount(
<Provider store={store}>
<CurrencyInput
onChange={handleChangeSpy}
hexValue="f602f2234d0ea"
featureSecondary
/>
</Provider>,
{
context: { t: (str) => `${str}_t` },
childContextTypes: { t: PropTypes.func },
},
const store = configureMockStore()(hideSecondaryState);
const props = {
onChange: jest.fn(),
hexValue: 'f602f2234d0ea',
featureSecondary: true,
};
const { container } = renderWithProvider(
<CurrencyInput {...props} />,
store,
);
expect(wrapper).toHaveLength(1);
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('ETH');
expect(wrapper.find('.unit-input__input').props().value).toStrictEqual(
0.00432788,
);
expect(
wrapper.find('.currency-input__conversion-component').text(),
).toStrictEqual('[noConversionRateAvailable]');
expect(container).toMatchSnapshot();
});
});
describe('handling actions', () => {
const handleChangeSpy = sinon.spy();
const handleBlurSpy = sinon.spy();
const handleChangeToggle = sinon.spy();
afterEach(() => {
handleChangeSpy.resetHistory();
handleBlurSpy.resetHistory();
handleChangeToggle.resetHistory();
});
it('should call onChange on input changes with the hex value for ETH', () => {
const mockStore = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
preferences: {
showFiatInTestnets: true,
},
},
};
const store = configureMockStore()(mockStore);
const wrapper = mount(
<Provider store={store}>
<CurrencyInput onChange={handleChangeSpy} hexValue="f602f2234d0ea" />
</Provider>,
const props = {
onChange: jest.fn(),
hexValue: 'f602f2234d0ea',
};
const { queryByTestId, queryByTitle } = renderWithProvider(
<CurrencyInput {...props} />,
store,
);
expect(wrapper).toHaveLength(1);
expect(handleChangeSpy.callCount).toStrictEqual(0);
expect(handleBlurSpy.callCount).toStrictEqual(0);
const currencyInput = queryByTestId('currency-input');
const input = wrapper.find('input');
expect(input.props().value).toStrictEqual(0.00432788);
fireEvent.change(currencyInput, { target: { value: 1 } });
input.simulate('change', { target: { value: 1 } });
expect(handleChangeSpy.callCount).toStrictEqual(1);
expect(handleChangeSpy.calledWith('de0b6b3a7640000')).toStrictEqual(true);
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
'$231.06USD',
);
expect(props.onChange).toHaveBeenCalledWith('de0b6b3a7640000');
expect(queryByTitle('$231.06 USD')).toBeInTheDocument();
});
it('should call onChange on input changes with the hex value for fiat', () => {
const mockStore = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
preferences: {
showFiatInTestnets: true,
},
},
};
const store = configureMockStore()(mockStore);
const wrapper = mount(
<Provider store={store}>
<CurrencyInput onChange={handleChangeSpy} featureSecondary />
</Provider>,
const props = {
onChange: jest.fn(),
hexValue: 'f602f2234d0ea',
featureSecondary: true,
};
const { queryByTestId, queryByTitle } = renderWithProvider(
<CurrencyInput {...props} />,
store,
);
expect(wrapper).toHaveLength(1);
expect(handleChangeSpy.callCount).toStrictEqual(1);
expect(handleBlurSpy.callCount).toStrictEqual(0);
const currencyInput = queryByTestId('currency-input');
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
'0ETH',
);
const input = wrapper.find('input');
expect(input.props().value).toStrictEqual(0);
fireEvent.change(currencyInput, { target: { value: 1 } });
input.simulate('change', { target: { value: 1 } });
expect(handleChangeSpy.callCount).toStrictEqual(2);
expect(handleChangeSpy.calledWith('f602f2234d0ea')).toStrictEqual(true);
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
'0.00432788ETH',
);
expect(props.onChange).toHaveBeenCalledWith('f602f2234d0ea');
expect(queryByTitle('0.00432788 ETH')).toBeInTheDocument();
});
it('should change the state and pass in a new decimalValue when props.value changes', () => {
const mockStore = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
preferences: {
showFiatInTestnets: true,
},
},
};
it('should swap selected currency when swap icon is clicked', async () => {
const store = configureMockStore()(mockStore);
const wrapper = mount(
<Provider store={store}>
<CurrencyInput onChange={handleChangeSpy} featureSecondary />
</Provider>,
);
expect(wrapper).toHaveLength(1);
const input = wrapper.find('input');
expect(input.props().value).toStrictEqual(0);
wrapper.setProps({ hexValue: '1ec05e43e72400' });
input.update();
expect(input.props().value).toStrictEqual(0);
});
it('should swap selected currency when swap icon is clicked', () => {
const mockStore = {
metamask: {
nativeCurrency: 'ETH',
currentCurrency: 'usd',
conversionRate: 231.06,
provider: {
chainId: '0x4',
},
preferences: {
showFiatInTestnets: true,
},
},
const props = {
onChange: jest.fn(),
onPreferenceToggle: jest.fn(),
featureSecondary: true,
};
const store = configureMockStore()(mockStore);
const wrapper = mount(
<Provider store={store}>
<CurrencyInput
onChange={handleChangeSpy}
onPreferenceToggle={handleChangeToggle}
featureSecondary
/>
</Provider>,
const { queryByTestId, queryByTitle } = renderWithProvider(
<CurrencyInput {...props} />,
store,
);
expect(wrapper).toHaveLength(1);
expect(handleChangeSpy.callCount).toStrictEqual(1);
expect(handleBlurSpy.callCount).toStrictEqual(0);
const currencyInput = queryByTestId('currency-input');
fireEvent.change(currencyInput, { target: { value: 1 } });
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
'0ETH',
);
const input = wrapper.find('input');
expect(input.props().value).toStrictEqual(0);
expect(queryByTitle('0.00432788 ETH')).toBeInTheDocument();
input.simulate('change', { target: { value: 1 } });
expect(handleChangeSpy.callCount).toStrictEqual(2);
expect(handleChangeSpy.calledWith('de0b6b3a7640000')).toStrictEqual(
false,
);
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
'0.00432788ETH',
);
const currencySwap = queryByTestId('currency-swap');
fireEvent.click(currencySwap);
const swap = wrapper.find('.currency-input__swap-component');
swap.simulate('click');
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
'0.00432788ETH',
);
await waitFor(() => {
expect(queryByTitle('$1.00 USD')).toBeInTheDocument();
});
});
});
});

View File

@ -0,0 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Dropdown should matchsnapshot 1`] = `
<div>
<li
class="dropdown-menu-item"
data-testid="dropdown-menu-item"
style="list-style: none; padding: 8px 0px; font-size: 18px; font-style: normal; cursor: pointer; display: flex; justify-content: flex-start; align-items: center;"
tabindex="0"
/>
</div>
`;

View File

@ -68,6 +68,7 @@ export class DropdownMenuItem extends Component {
return (
<li
className="dropdown-menu-item"
data-testid="dropdown-menu-item"
onClick={() => {
onClick();
closeMenu();

View File

@ -1,34 +1,31 @@
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import { fireEvent } from '@testing-library/react';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import { DropdownMenuItem } from './dropdown';
describe('Dropdown', () => {
let wrapper;
const onClickSpy = sinon.spy();
const closeMenuSpy = sinon.spy();
const props = {
onClick: jest.fn(),
closeMenu: jest.fn(),
style: { test: 'style' },
};
beforeEach(() => {
wrapper = shallow(
<DropdownMenuItem
onClick={onClickSpy}
style={{ test: 'style' }}
closeMenu={closeMenuSpy}
/>,
);
});
it('should matchsnapshot', () => {
const { container } = renderWithProvider(<DropdownMenuItem {...props} />);
it('renders li with dropdown-menu-item class', () => {
expect(wrapper.find('li.dropdown-menu-item')).toHaveLength(1);
});
it('adds style based on props passed', () => {
expect(wrapper.prop('style').test).toStrictEqual('style');
expect(container).toMatchSnapshot();
});
it('simulates click event and calls onClick and closeMenu', () => {
wrapper.prop('onClick')();
expect(onClickSpy.callCount).toStrictEqual(1);
expect(closeMenuSpy.callCount).toStrictEqual(1);
const { queryByTestId } = renderWithProvider(
<DropdownMenuItem {...props} />,
);
const dropdownItem = queryByTestId('dropdown-menu-item');
fireEvent.click(dropdownItem);
expect(props.onClick).toHaveBeenCalledTimes(1);
expect(props.closeMenu).toHaveBeenCalledTimes(1);
});
});

View File

@ -0,0 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`InfoBox should match snapshot 1`] = `
<div>
<div
class="info-box"
>
<div
class="info-box__close"
data-testid="info-box-close"
/>
<div
class="info-box__title"
>
Title
</div>
<div
class="info-box__description"
>
Description
</div>
</div>
</div>
`;

View File

@ -31,7 +31,11 @@ export default class InfoBox extends Component {
return this.state.isShowing ? (
<div className="info-box">
<div className="info-box__close" onClick={() => this.handleClose()} />
<div
className="info-box__close"
data-testid="info-box-close"
onClick={() => this.handleClose()}
/>
<div className="info-box__title">{title}</div>
<div className="info-box__description">{description}</div>
</div>

View File

@ -1,35 +1,26 @@
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import { fireEvent } from '@testing-library/react';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import InfoBox from './info-box.component';
describe('InfoBox', () => {
let wrapper;
const props = {
title: 'Title',
description: 'Description',
onClose: sinon.spy(),
onClose: jest.fn(),
};
beforeEach(() => {
wrapper = shallow(<InfoBox {...props} />);
it('should match snapshot', () => {
const { container } = renderWithProvider(<InfoBox {...props} />);
expect(container).toMatchSnapshot();
});
it('renders title from props', () => {
const title = wrapper.find('.info-box__title');
expect(title.text()).toStrictEqual(props.title);
});
it('should call handleClose on info close element', () => {
const { queryByTestId } = renderWithProvider(<InfoBox {...props} />);
const infoBoxClose = queryByTestId('info-box-close');
it('renders description from props', () => {
const description = wrapper.find('.info-box__description');
expect(description.text()).toStrictEqual(props.description);
});
it('closes info box', () => {
const close = wrapper.find('.info-box__close');
close.simulate('click');
expect(props.onClose.calledOnce).toStrictEqual(true);
fireEvent.click(infoBoxClose);
expect(props.onClose).toHaveBeenCalled();
});
});

View File

@ -0,0 +1,157 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Modal Component should render a modal with a cancel and a submit button 1`] = `
<div>
<div
class="modal-container"
>
<div
class="modal-container__content"
/>
<div
class="modal-container__footer"
>
<button
class="button btn--rounded btn-secondary modal-container__footer-button"
role="button"
tabindex="0"
>
Cancel
</button>
<button
class="button btn--rounded btn-primary modal-container__footer-button"
role="button"
tabindex="0"
>
Submit
</button>
</div>
</div>
</div>
`;
exports[`Modal Component should render a modal with a header 1`] = `
<div>
<div
class="modal-container"
>
<div
class="modal-container__header"
>
<div
class="modal-container__header-text"
>
My Header
</div>
<div
class="modal-container__header-close"
data-testid="modal-header-close"
/>
</div>
<div
class="modal-container__content"
/>
<div
class="modal-container__footer"
>
<button
class="button btn--rounded btn-secondary modal-container__footer-button"
role="button"
tabindex="0"
>
Cancel
</button>
<button
class="button btn--rounded btn-primary modal-container__footer-button"
role="button"
tabindex="0"
>
Submit
</button>
</div>
</div>
</div>
`;
exports[`Modal Component should render a modal with a submit button 1`] = `
<div>
<div
class="modal-container"
>
<div
class="modal-container__content"
/>
<div
class="modal-container__footer"
>
<button
class="button btn--rounded btn-primary modal-container__footer-button"
/>
</div>
</div>
</div>
`;
exports[`Modal Component should render a modal with children 1`] = `
<div>
<div
class="modal-container"
>
<div
class="modal-container__content"
>
<div
class="test-child"
/>
</div>
<div
class="modal-container__footer"
>
<button
class="button btn--rounded btn-secondary modal-container__footer-button"
role="button"
tabindex="0"
>
Cancel
</button>
<button
class="button btn--rounded btn-primary modal-container__footer-button"
role="button"
tabindex="0"
>
Submit
</button>
</div>
</div>
</div>
`;
exports[`Modal Component should render a modal with different button types 1`] = `
<div>
<div
class="modal-container"
>
<div
class="modal-container__content"
/>
<div
class="modal-container__footer"
>
<button
class="button btn--rounded btn-default modal-container__footer-button"
role="button"
tabindex="0"
>
Cancel
</button>
<button
class="button btn--rounded btn-default modal-container__footer-button"
role="button"
tabindex="0"
>
Submit
</button>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ModalContent Component should match snapshot 1`] = `
<div>
<div
class="modal-content"
>
<div
class="modal-content__title"
>
Modal Title
</div>
<div
class="modal-content__description"
>
Modal Description
</div>
</div>
</div>
`;

View File

@ -1,40 +1,15 @@
import React from 'react';
import { shallow } from 'enzyme';
import ModalContent from './modal-content.component';
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
import ModalContent from '.';
describe('ModalContent Component', () => {
it('should render a title', () => {
const wrapper = shallow(<ModalContent title="Modal Title" />);
const props = {
title: 'Modal Title',
description: 'Modal Description',
};
it('should match snapshot', () => {
const { container } = renderWithProvider(<ModalContent {...props} />);
expect(wrapper.find('.modal-content__title')).toHaveLength(1);
expect(wrapper.find('.modal-content__title').text()).toStrictEqual(
'Modal Title',
);
expect(wrapper.find('.modal-content__description')).toHaveLength(0);
});
it('should render a description', () => {
const wrapper = shallow(<ModalContent description="Modal Description" />);
expect(wrapper.find('.modal-content__title')).toHaveLength(0);
expect(wrapper.find('.modal-content__description')).toHaveLength(1);
expect(wrapper.find('.modal-content__description').text()).toStrictEqual(
'Modal Description',
);
});
it('should render both a title and a description', () => {
const wrapper = shallow(
<ModalContent title="Modal Title" description="Modal Description" />,
);
expect(wrapper.find('.modal-content__title')).toHaveLength(1);
expect(wrapper.find('.modal-content__title').text()).toStrictEqual(
'Modal Title',
);
expect(wrapper.find('.modal-content__description')).toHaveLength(1);
expect(wrapper.find('.modal-content__description').text()).toStrictEqual(
'Modal Description',
);
expect(container).toMatchSnapshot();
});
});

View File

@ -50,7 +50,11 @@ export default class Modal extends PureComponent {
{headerText && (
<div className="modal-container__header">
<div className="modal-container__header-text">{headerText}</div>
<div className="modal-container__header-close" onClick={onClose} />
<div
className="modal-container__header-close"
data-testid="modal-header-close"
onClick={onClose}
/>
</div>
)}
<div className={classnames('modal-container__content', contentClass)}>

View File

@ -1,133 +1,103 @@
import React from 'react';
import { mount, shallow } from 'enzyme';
import sinon from 'sinon';
import Button from '../../ui/button';
import { fireEvent } from '@testing-library/react';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import Modal from './modal.component';
describe('Modal Component', () => {
it('should render a modal with a submit button', () => {
const wrapper = shallow(<Modal />);
const { container } = renderWithProvider(<Modal />);
expect(wrapper.find('.modal-container')).toHaveLength(1);
const buttons = wrapper.find(Button);
expect(buttons).toHaveLength(1);
expect(buttons.at(0).props().type).toStrictEqual('primary');
expect(container).toMatchSnapshot();
});
it('should render a modal with a cancel and a submit button', () => {
const handleCancel = sinon.spy();
const handleSubmit = sinon.spy();
const wrapper = shallow(
<Modal
onCancel={handleCancel}
cancelText="Cancel"
onSubmit={handleSubmit}
submitText="Submit"
/>,
);
const props = {
onCancel: jest.fn(),
cancelText: 'Cancel',
onSubmit: jest.fn(),
submitText: 'Submit',
};
const { container, queryByText } = renderWithProvider(<Modal {...props} />);
expect(container).toMatchSnapshot();
const buttons = wrapper.find(Button);
expect(buttons).toHaveLength(2);
const cancelButton = buttons.at(0);
const submitButton = buttons.at(1);
const cancelButton = queryByText(props.cancelText);
const submitButton = queryByText(props.submitText);
expect(cancelButton.props().type).toStrictEqual('secondary');
expect(cancelButton.props().children).toStrictEqual('Cancel');
expect(handleCancel.callCount).toStrictEqual(0);
cancelButton.simulate('click');
expect(handleCancel.callCount).toStrictEqual(1);
expect(props.onCancel).not.toHaveBeenCalled();
fireEvent.click(cancelButton);
expect(props.onCancel).toHaveBeenCalled();
expect(submitButton.props().type).toStrictEqual('primary');
expect(submitButton.props().children).toStrictEqual('Submit');
expect(handleSubmit.callCount).toStrictEqual(0);
submitButton.simulate('click');
expect(handleSubmit.callCount).toStrictEqual(1);
expect(props.onSubmit).not.toHaveBeenCalled();
fireEvent.click(submitButton);
expect(props.onSubmit).toHaveBeenCalled();
});
it('should render a modal with different button types', () => {
const wrapper = shallow(
<Modal
onCancel={() => undefined}
cancelText="Cancel"
cancelType="default"
onSubmit={() => undefined}
submitText="Submit"
submitType="confirm"
/>,
);
const props = {
onCancel: () => undefined,
cancelText: 'Cancel',
cancelType: 'default',
onSubmit: () => undefined,
submitText: 'Submit',
submitType: 'confirm',
};
const buttons = wrapper.find(Button);
expect(buttons).toHaveLength(2);
expect(buttons.at(0).props().type).toStrictEqual('default');
expect(buttons.at(1).props().type).toStrictEqual('confirm');
const { container } = renderWithProvider(<Modal {...props} />);
expect(container).toMatchSnapshot();
});
it('should render a modal with children', () => {
const wrapper = shallow(
<Modal
onCancel={() => undefined}
cancelText="Cancel"
onSubmit={() => undefined}
submitText="Submit"
>
const props = {
onCancel: () => undefined,
cancelText: 'Cancel',
onSubmit: () => undefined,
submitText: 'Submit',
};
const { container } = renderWithProvider(
<Modal {...props}>
<div className="test-child" />
</Modal>,
);
expect(wrapper.find('.test-child')).toHaveLength(1);
expect(container).toMatchSnapshot();
});
it('should render a modal with a header', () => {
const handleCancel = sinon.spy();
const handleSubmit = sinon.spy();
const wrapper = shallow(
<Modal
onCancel={handleCancel}
cancelText="Cancel"
onSubmit={handleSubmit}
submitText="Submit"
headerText="My Header"
onClose={handleCancel}
/>,
);
const props = {
onCancel: jest.fn(),
cancelText: 'Cancel',
onSubmit: jest.fn(),
submitText: 'Submit',
headerText: 'My Header',
onClose: jest.fn(),
};
expect(wrapper.find('.modal-container__header')).toHaveLength(1);
expect(wrapper.find('.modal-container__header-text').text()).toStrictEqual(
'My Header',
const { container, queryByTestId } = renderWithProvider(
<Modal {...props} />,
);
expect(handleCancel.callCount).toStrictEqual(0);
expect(handleSubmit.callCount).toStrictEqual(0);
wrapper.find('.modal-container__header-close').simulate('click');
expect(handleCancel.callCount).toStrictEqual(1);
expect(handleSubmit.callCount).toStrictEqual(0);
expect(container).toMatchSnapshot();
const modalClose = queryByTestId('modal-header-close');
fireEvent.click(modalClose);
expect(props.onClose).toHaveBeenCalled();
});
it('should disable the submit button if submitDisabled is true', () => {
const handleCancel = sinon.spy();
const handleSubmit = sinon.spy();
const wrapper = mount(
<Modal
onCancel={handleCancel}
cancelText="Cancel"
onSubmit={handleSubmit}
submitText="Submit"
submitDisabled
headerText="My Header"
onClose={handleCancel}
/>,
);
const props = {
onCancel: jest.fn(),
cancelText: 'Cancel',
onSubmit: jest.fn(),
submitText: 'Submit',
submitDisabled: true,
headerText: 'My Header',
onClose: jest.fn(),
};
const { queryByText } = renderWithProvider(<Modal {...props} />);
const submitButton = queryByText(props.submitText);
const buttons = wrapper.find(Button);
expect(buttons).toHaveLength(2);
const cancelButton = buttons.at(0);
const submitButton = buttons.at(1);
expect(submitButton).toHaveAttribute('disabled');
expect(handleCancel.callCount).toStrictEqual(0);
cancelButton.simulate('click');
expect(handleCancel.callCount).toStrictEqual(1);
expect(submitButton.props().disabled).toStrictEqual(true);
expect(handleSubmit.callCount).toStrictEqual(0);
submitButton.simulate('click');
expect(handleSubmit.callCount).toStrictEqual(0);
fireEvent.click(submitButton);
expect(props.onSubmit).not.toHaveBeenCalled();
});
});

View File

@ -13,6 +13,7 @@ function removeLeadingZeroes(str) {
*/
export default class UnitInput extends PureComponent {
static propTypes = {
dataTestId: PropTypes.string,
children: PropTypes.node,
actionComponent: PropTypes.node,
error: PropTypes.bool,
@ -80,8 +81,14 @@ export default class UnitInput extends PureComponent {
}
render() {
const { error, placeholder, suffix, actionComponent, children } =
this.props;
const {
error,
placeholder,
suffix,
actionComponent,
children,
dataTestId,
} = this.props;
const { value } = this.state;
return (
@ -92,6 +99,7 @@ export default class UnitInput extends PureComponent {
<div className="unit-input__inputs">
<div className="unit-input__input-container">
<input
data-testid={dataTestId}
type="number"
dir="ltr"
className={classnames('unit-input__input')}