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

feature/default_network_editable
Thomas Huang 2 years ago committed by GitHub
parent 9efdf87e86
commit aff2d82bb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 216
      ui/components/app/currency-input/__snapshots__/currency-input.test.js.snap
  2. 7
      ui/components/app/currency-input/currency-input.js
  3. 354
      ui/components/app/currency-input/currency-input.test.js
  4. 12
      ui/components/app/dropdowns/__snapshots__/dropdown.test.js.snap
  5. 1
      ui/components/app/dropdowns/dropdown.js
  6. 43
      ui/components/app/dropdowns/dropdown.test.js
  7. 24
      ui/components/app/info-box/__snapshots__/info-box.test.js.snap
  8. 6
      ui/components/app/info-box/info-box.component.js
  9. 31
      ui/components/app/info-box/info-box.test.js
  10. 157
      ui/components/app/modal/__snapshots__/modal.component.test.js.snap
  11. 20
      ui/components/app/modal/modal-content/__snapshots__/modal-content.component.test.js.snap
  12. 45
      ui/components/app/modal/modal-content/modal-content.component.test.js
  13. 6
      ui/components/app/modal/modal.component.js
  14. 172
      ui/components/app/modal/modal.component.test.js
  15. 12
      ui/components/ui/unit-input/unit-input.component.js

@ -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>
`;

@ -146,11 +146,16 @@ export default function CurrencyInput({
onChange, onChange,
onPreferenceToggle, onPreferenceToggle,
}} }}
dataTestId="currency-input"
suffix={shouldUseFiat ? secondarySuffix : primarySuffix} suffix={shouldUseFiat ? secondarySuffix : primarySuffix}
onChange={handleChange} onChange={handleChange}
value={initialDecimalValue} value={initialDecimalValue}
actionComponent={ 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" /> <i className="fa fa-retweet fa-lg" />
</button> </button>
} }

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

@ -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>
`;

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

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

@ -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>
`;

@ -31,7 +31,11 @@ export default class InfoBox extends Component {
return this.state.isShowing ? ( return this.state.isShowing ? (
<div className="info-box"> <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__title">{title}</div>
<div className="info-box__description">{description}</div> <div className="info-box__description">{description}</div>
</div> </div>

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

@ -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>
`;

@ -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>
`;

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

@ -50,7 +50,11 @@ export default class Modal extends PureComponent {
{headerText && ( {headerText && (
<div className="modal-container__header"> <div className="modal-container__header">
<div className="modal-container__header-text">{headerText}</div> <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>
)} )}
<div className={classnames('modal-container__content', contentClass)}> <div className={classnames('modal-container__content', contentClass)}>

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

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

Loading…
Cancel
Save