feat: mock paragon and i18n library for tests
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -102,3 +102,9 @@ dist
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
### Emacs/vi ###
|
||||
*~
|
||||
*.swo
|
||||
*.swp
|
||||
|
||||
|
||||
Binary file not shown.
@@ -43,3 +43,41 @@ process.env.LOGO_URL = 'https://edx-cdn.org/v3/default/logo.svg';
|
||||
process.env.LOGO_TRADEMARK_URL = 'https://edx-cdn.org/v3/default/logo-trademark.svg';
|
||||
process.env.LOGO_WHITE_URL = 'https://edx-cdn.org/v3/default/logo-white.svg';
|
||||
process.env.FAVICON_URL = 'https://edx-cdn.org/v3/default/favicon.ico';
|
||||
|
||||
jest.mock('@edx/frontend-platform/i18n', () => {
|
||||
const i18n = jest.requireActual('@edx/frontend-platform/i18n');
|
||||
const PropTypes = jest.requireActual('prop-types');
|
||||
return {
|
||||
...i18n,
|
||||
intlShape: PropTypes.shape({
|
||||
formatMessage: PropTypes.func,
|
||||
}),
|
||||
defineMessages: m => m,
|
||||
FormattedMessage: () => 'FormattedMessage',
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@edx/paragon', () => jest.requireActual('testUtils').mockNestedComponents({
|
||||
ActionRow: 'ActionRow',
|
||||
Button: 'Button',
|
||||
Icon: 'Icon',
|
||||
IconButton: 'IconButton',
|
||||
ModalDialog: {
|
||||
Header: 'ModalDialog.Header',
|
||||
Title: 'ModalDialog.Title',
|
||||
},
|
||||
Form: {
|
||||
Control: {
|
||||
Feedback: 'Form.Control.Feedback',
|
||||
},
|
||||
Group: 'Form.Group',
|
||||
Label: 'Form.Label',
|
||||
},
|
||||
Spinner: 'Spinner',
|
||||
Toast: 'Toast',
|
||||
}));
|
||||
|
||||
jest.mock('@edx/paragon/icons', () => ({
|
||||
Close: jest.fn().mockName('icons.Close'),
|
||||
Edit: jest.fn().mockName('icons.Edit'),
|
||||
}));
|
||||
|
||||
59
src/testUtils.js
Normal file
59
src/testUtils.js
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Mocked formatMessage provided by react-intl
|
||||
*/
|
||||
export const formatMessage = (msg, values) => {
|
||||
let message = msg.defaultMessage;
|
||||
if (values === undefined) {
|
||||
return message;
|
||||
}
|
||||
Object.keys(values).forEach((key) => {
|
||||
// eslint-disable-next-line
|
||||
message = message.replace(`{${key}}`, values[key]);
|
||||
});
|
||||
return message;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mock a single component, or a nested component so that its children render nicely
|
||||
* in snapshots.
|
||||
* @param {string} name - parent component name
|
||||
* @param {obj} contents - object of child components with intended component
|
||||
* render name.
|
||||
* @return {func} - mock component with nested children.
|
||||
*
|
||||
* usage:
|
||||
* mockNestedComponent('Card', { Body: 'Card.Body', Form: { Control: { Feedback: 'Form.Control.Feedback' }}... });
|
||||
* mockNestedComponent('IconButton', 'IconButton');
|
||||
*/
|
||||
export const mockNestedComponent = (name, contents) => {
|
||||
if (typeof contents !== 'object') {
|
||||
return contents;
|
||||
}
|
||||
const fn = () => name;
|
||||
Object.defineProperty(fn, 'name', { value: name });
|
||||
Object.keys(contents).forEach((nestedName) => {
|
||||
const value = contents[nestedName];
|
||||
fn[nestedName] = typeof value !== 'object'
|
||||
? value
|
||||
: mockNestedComponent(`${name}.${nestedName}`, value);
|
||||
});
|
||||
return fn;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mock a module of components. nested components will be rendered nicely in snapshots.
|
||||
* @param {obj} mapping - component module mock config.
|
||||
* @return {obj} - module of flat and nested components that will render nicely in snapshots.
|
||||
* usage:
|
||||
* mockNestedComponents({
|
||||
* Card: { Body: 'Card.Body' },
|
||||
* IconButton: 'IconButton',
|
||||
* })
|
||||
*/
|
||||
export const mockNestedComponents = (mapping) => Object.entries(mapping).reduce(
|
||||
(obj, [name, value]) => ({
|
||||
...obj,
|
||||
[name]: mockNestedComponent(name, value),
|
||||
}),
|
||||
{},
|
||||
);
|
||||
Reference in New Issue
Block a user