Skip to content

Commit

Permalink
Merge pull request #496 from creative-commoners/pulls/5.0/react-testi…
Browse files Browse the repository at this point in the history
…ng-library

MNT Use React Testing Library
  • Loading branch information
GuySartorelli authored May 3, 2023
2 parents 2a92573 + d394fa6 commit 6ab6b40
Show file tree
Hide file tree
Showing 24 changed files with 1,410 additions and 2,489 deletions.
2 changes: 1 addition & 1 deletion client/dist/js/bundle-cms.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

164 changes: 47 additions & 117 deletions client/src/components/BackupCodes/tests/Register-test.js
Original file line number Diff line number Diff line change
@@ -1,127 +1,57 @@
/* global jest */
/* global jest, test */

import React from 'react';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Register from '../Register';

Enzyme.configure({ adapter: new Adapter() });
import { render, fireEvent, screen } from '@testing-library/react';

window.ss = {
i18n: { _t: (key, string) => string },
};

const mockMethod = {
urlSegment: 'aye',
name: 'Aye',
description: 'Register using aye',
supportLink: 'https://google.com',
component: 'Test',
};

describe('Register - Recovery Codes', () => {
it('will show a recently copied message when using the copy test button', () => {
const preventDefault = jest.fn();

const wrapper = shallow(
<Register
method={mockMethod}
codes={['123', '456']}
copyFeedbackDuration={30}
/>
);

const copyLink = wrapper.find('.mfa-register-backup-codes__copy-to-clipboard');

expect(copyLink.text()).toBe('Copy codes');
copyLink.simulate('click', { preventDefault });

expect(preventDefault.mock.calls).toHaveLength(1);

wrapper.update();

expect(wrapper.find('.mfa-register-backup-codes__copy-to-clipboard').text()).toBe('Copied!');
});

it('will hide the recently copied message after a short delay', done => {
const preventDefault = jest.fn();

const wrapper = shallow(
<Register
method={mockMethod}
codes={['123', '456']}
copyFeedbackDuration={30}
/>
);

const copyLink = wrapper.find('.mfa-register-backup-codes__copy-to-clipboard');

expect(copyLink.text()).toBe('Copy codes');
copyLink.simulate('click', { preventDefault });

expect(preventDefault.mock.calls).toHaveLength(1);

wrapper.update();

expect(wrapper.find('.mfa-register-backup-codes__copy-to-clipboard').text()).toBe('Copied!');

setTimeout(() => {
expect(wrapper.find('.mfa-register-backup-codes__copy-to-clipboard').text())
.toBe('Copy codes');
done();
}, 40);
});

it('re-copying the codes will reset the recently copied timer', done => {
const preventDefault = jest.fn();

const wrapper = shallow(
<Register
method={mockMethod}
codes={['123', '456']}
copyFeedbackDuration={300}
/>
);

const copyLink = wrapper.find('.mfa-register-backup-codes__copy-to-clipboard');

expect(copyLink.text()).toBe('Copy codes');
copyLink.simulate('click', { preventDefault });

expect(preventDefault.mock.calls).toHaveLength(1);

wrapper.update();

expect(wrapper.find('.mfa-register-backup-codes__copy-to-clipboard').text()).toBe('Copied!');

setTimeout(() => {
expect(wrapper.find('.mfa-register-backup-codes__copy-to-clipboard').text())
.toBe('Copied!');
copyLink.simulate('click', { preventDefault });
expect(preventDefault.mock.calls).toHaveLength(2);
wrapper.update();
}, 150);

setTimeout(() => {
expect(wrapper.find('.mfa-register-backup-codes__copy-to-clipboard').text())
.toBe('Copied!');
done();
}, 400);
});

it('will call the given onComplete function when pressing the "finish" button', () => {
const completeFunction = jest.fn();

const wrapper = shallow(
<Register
method={mockMethod}
codes={['123', '456']}
onCompleteRegistration={completeFunction}
/>
);

wrapper.find('button.btn-primary').simulate('click');
window.prompt = () => {};

function makeProps(obj = {}) {
return {
method: {
urlSegment: 'aye',
name: 'Aye',
description: 'Register using aye',
supportLink: 'https://google.com',
component: 'Test',
},
codes: ['123', '456'],
copyFeedbackDuration: 30,
...obj
};
}

test('Register will show a recently copied message when using the copy test button and hide after a short delay', async () => {
const { container } = render(<Register {...makeProps()}/>);
let link = container.querySelector('.mfa-register-backup-codes__copy-to-clipboard');
expect(link.textContent).toBe('Copy codes');
fireEvent.click(link);
link = await screen.findByText('Copied!');
expect(link.classList).toContain('mfa-register-backup-codes__copy-to-clipboard');
expect(screen.queryByText('Copy codes!')).toBeNull();
link = await screen.findByText('Copy codes');
expect(link.classList).toContain('mfa-register-backup-codes__copy-to-clipboard');
expect(screen.queryByText('Copied!')).toBeNull();
// Can do this multiple times
fireEvent.click(link);
link = await screen.findByText('Copied!');
expect(link).not.toBeNull();
link = await screen.findByText('Copy codes');
expect(link).not.toBeNull();
});

expect(completeFunction.mock.calls).toHaveLength(1);
});
test('Register will call the given onComplete function when pressing the "finish" button', () => {
const onCompleteRegistration = jest.fn();
const { container } = render(
<Register {...makeProps({
onCompleteRegistration
})}
/>
);
fireEvent.click(container.querySelector('button.btn-primary'));
expect(onCompleteRegistration).toHaveBeenCalled();
});
77 changes: 33 additions & 44 deletions client/src/components/BackupCodes/tests/Verify-test.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,45 @@
/* global jest */
/* global jest, test */

import React from 'react';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Verify from '../Verify';

Enzyme.configure({ adapter: new Adapter() });
import { render, fireEvent } from '@testing-library/react';

window.ss = {
i18n: { _t: (key, string) => string },
};

describe('Login - Recovery Codes', () => {
it('has a disabled button on load', () => {
const wrapper = shallow(<Verify />);

expect(wrapper.find('button').prop('disabled')).toBe(true);
});

it('will un-disable the button when input is provided', () => {
const wrapper = shallow(<Verify />);

wrapper.setState({
value: 'something',
});
wrapper.update();

expect(wrapper.find('button').prop('disabled')).toBe(false);
});

it('renders the given "more options control"', () => {
const moreOptions = <div>More options!</div>;

const wrapper = shallow(<Verify moreOptionsControl={moreOptions} />);

expect(wrapper.html()).toMatch(/<div>More options!<\/div>/);
});

it('triggers login completion with the right value when the button is pressed', () => {
const completeFunction = jest.fn();
const preventDefault = jest.fn();

const wrapper = shallow(<Verify onCompleteVerification={completeFunction} />);
test('Verify has a disabled button on load', () => {
const { container } = render(<Verify />);
expect(container.querySelector('button.btn-primary').disabled).toBe(true);
});

wrapper.setState({
value: 'something',
});
test('Verify will un-disable the button when input is provided', () => {
const { container } = render(<Verify />);
const input = container.querySelector('input.mfa-verify-backup-codes__input');
fireEvent.change(input, { target: { value: 'x' } });
expect(container.querySelector('button.btn-primary').disabled).toBe(false);
});

wrapper.find('button').simulate('click', { preventDefault });
test('Verify renders the given "more options control"', () => {
const { container } = render(
<Verify {...{
moreOptionsControl: <div>More options!</div>
}}
/>
);
expect(container.querySelectorAll('.mfa-action-list__item')[1].textContent).toBe('More options!');
});

expect(preventDefault.mock.calls).toHaveLength(1);
expect(completeFunction.mock.calls).toHaveLength(1);
expect(completeFunction.mock.calls[0]).toEqual([{ code: 'something' }]);
});
test('Verify triggers login completion with the right value when the button is pressed', () => {
const onCompleteVerification = jest.fn();
const { container } = render(
<Verify {...{
onCompleteVerification
}}
/>
);
const input = container.querySelector('input.mfa-verify-backup-codes__input');
fireEvent.change(input, { target: { value: 'something' } });
fireEvent.click(container.querySelector('button.btn-primary'));
expect(onCompleteVerification).toBeCalledWith({ code: 'something' });
});
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,12 @@ class AccountResetUI extends Component {
*/
renderSending() {
const { ss: { i18n } } = window;
const { LoadingIndicatorComponent } = this.props;

return (
<p className="account-reset-action account-reset-action--sending">
<span className="account-reset-action__icon">
<LoadingIndicator size="32px" />
<LoadingIndicatorComponent size="32px" />
</span>
<span className="account-reset-action__message">
{
Expand Down Expand Up @@ -236,6 +237,11 @@ class AccountResetUI extends Component {

AccountResetUI.propTypes = {
resetEndpoint: PropTypes.string,
LoadingIndicatorComponent: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
};

AccountResetUI.defaultProps = {
LoadingIndicatorComponent: LoadingIndicator,
};

export default AccountResetUI;
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ class MethodListItem extends PureComponent {
}

renderRemove() {
const { canRemove, method } = this.props;
const { canRemove, method, RemoveComponent } = this.props;

if (!canRemove) {
return null;
}

return <Remove method={method} />;
return <RemoveComponent method={method} />;
}

renderReset() {
Expand Down Expand Up @@ -104,13 +104,13 @@ class MethodListItem extends PureComponent {
* @returns {SetDefault}
*/
renderSetAsDefault() {
const { isDefaultMethod, isBackupMethod, method } = this.props;
const { isDefaultMethod, isBackupMethod, method, SetDefaultComponent } = this.props;

if (isDefaultMethod || isBackupMethod) {
return null;
}

return <SetDefault method={method} />;
return <SetDefaultComponent method={method} />;
}


Expand All @@ -123,9 +123,9 @@ class MethodListItem extends PureComponent {

return (
<div>
{ this.renderRemove() }
{ this.renderReset() }
{ this.renderSetAsDefault() }
{ this.renderRemove() }
{ this.renderReset() }
{ this.renderSetAsDefault() }
</div>
);
}
Expand Down Expand Up @@ -156,8 +156,8 @@ class MethodListItem extends PureComponent {

return (
<Tag className={classes}>
{ this.renderNameAndStatus() }
{ this.renderControls() }
{ this.renderNameAndStatus() }
{ this.renderControls() }
</Tag>
);
}
Expand All @@ -174,6 +174,8 @@ MethodListItem.propTypes = {
createdDate: PropTypes.string,
className: PropTypes.string,
tag: PropTypes.string,
RemoveComponent: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
SetDefaultComponent: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
};

MethodListItem.defaultProps = {
Expand All @@ -182,6 +184,8 @@ MethodListItem.defaultProps = {
canRemove: false,
canReset: false,
tag: 'li',
RemoveComponent: Remove,
SetDefaultComponent: SetDefault
};

export default MethodListItem;
Loading

0 comments on commit 6ab6b40

Please sign in to comment.