diff --git a/.eslintrc.js b/.eslintrc.js
index b6094c794e6f..ae8b384bff5b 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -129,7 +129,12 @@ module.exports = {
},
},
{
- files: ['ui/**/*.test.js', 'ui/__mocks__/*.js', 'shared/**/*.test.js'],
+ files: [
+ 'ui/**/*.test.js',
+ 'ui/__mocks__/*.js',
+ 'shared/**/*.test.js',
+ 'test/jest/*.js',
+ ],
extends: ['@metamask/eslint-config-jest'],
rules: {
'jest/no-restricted-matchers': 'off',
diff --git a/test/jest/index.js b/test/jest/index.js
index 098877489808..b68672d34541 100644
--- a/test/jest/index.js
+++ b/test/jest/index.js
@@ -1,3 +1,5 @@
+import './matchers';
+
export { createSwapsMockStore } from './mock-store';
export { renderWithProvider } from './rendering';
export { setBackgroundConnection } from './background';
diff --git a/test/jest/matchers.js b/test/jest/matchers.js
new file mode 100644
index 000000000000..660018b40ed0
--- /dev/null
+++ b/test/jest/matchers.js
@@ -0,0 +1,35 @@
+import { shallow, mount } from 'enzyme';
+
+const SHALLOW_WRAPPER_CONSTRUCTOR = 'ShallowWrapper';
+
+function isShallowWrapper(wrapper) {
+ return wrapper.constructor.name
+ ? wrapper.constructor.name === SHALLOW_WRAPPER_CONSTRUCTOR
+ : Boolean(`${wrapper.constructor}`.match(/^function ShallowWrapper\(/u));
+}
+
+function toMatchElement(
+ actualEnzymeWrapper,
+ reactInstance,
+ options = { ignoreProps: true },
+) {
+ const expectedWrapper = isShallowWrapper(actualEnzymeWrapper)
+ ? shallow(reactInstance)
+ : mount(reactInstance);
+
+ const actual = actualEnzymeWrapper.debug({ verbose: true, ...options });
+ const expected = expectedWrapper.debug({ verbose: true, ...options });
+ const pass = actual === expected;
+
+ return {
+ pass,
+ message: 'Expected actual value to match the expected value.',
+ negatedMessage: 'Did not expect actual value to match the expected value.',
+ contextualInformation: {
+ actual: `Actual:\n ${actual}`,
+ expected: `Expected:\n ${expected}`,
+ },
+ };
+}
+
+expect.extend({ toMatchElement });
diff --git a/test/jest/setup.js b/test/jest/setup.js
index 6176cfc660db..db848f08a8d2 100644
--- a/test/jest/setup.js
+++ b/test/jest/setup.js
@@ -1,2 +1,3 @@
// This file is for Jest-specific setup only and runs before our Jest tests.
import '@testing-library/jest-dom';
+import './matchers';
diff --git a/ui/components/app/contact-list/contact-list.component.js b/ui/components/app/contact-list/contact-list.component.js
index 04e3a3abd0a9..713edfcfb98d 100644
--- a/ui/components/app/contact-list/contact-list.component.js
+++ b/ui/components/app/contact-list/contact-list.component.js
@@ -1,5 +1,6 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
+import { sortBy } from 'lodash';
import Button from '../../ui/button';
import RecipientGroup from './recipient-group/recipient-group.component';
@@ -50,34 +51,36 @@ export default class ContactList extends PureComponent {
}
renderAddressBook() {
- const contacts = this.props.searchForContacts();
+ const unsortedContactsByLetter = this.props
+ .searchForContacts()
+ .reduce((obj, contact) => {
+ const firstLetter = contact.name[0].toUpperCase();
+ return {
+ ...obj,
+ [firstLetter]: [...(obj[firstLetter] || []), contact],
+ };
+ }, {});
- const contactGroups = contacts.reduce((acc, contact) => {
- const firstLetter = contact.name.slice(0, 1).toUpperCase();
- acc[firstLetter] = acc[firstLetter] || [];
- const bucket = acc[firstLetter];
- bucket.push(contact);
- return acc;
- }, {});
+ const letters = Object.keys(unsortedContactsByLetter).sort();
- return Object.entries(contactGroups)
- .sort(([letter1], [letter2]) => {
- if (letter1 > letter2) {
- return 1;
- } else if (letter1 === letter2) {
- return 0;
- }
- return -1;
- })
- .map(([letter, groupItems]) => (
-