Fix front unit tests

This commit is contained in:
soupette 2019-04-23 15:18:57 +02:00
parent ff31c75c47
commit adf4e88ebb
41 changed files with 582 additions and 176 deletions

View File

@ -1,12 +0,0 @@
{
"presets": ["babel-preset-env", "babel-preset-react", "babel-preset-stage-0"],
"plugins": [
"babel-plugin-transform-class-properties",
"babel-plugin-transform-react-remove-prop-types",
"babel-plugin-transform-react-constant-elements",
"babel-plugin-transform-react-inline-elements",
"babel-plugin-transform-es2015-destructuring",
"babel-plugin-transform-es2015-parameters",
"babel-plugin-transform-object-rest-spread"
]
}

10
babel.config.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
presets: [
require.resolve('@babel/preset-env'),
require.resolve('@babel/preset-react'),
],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-syntax-dynamic-import',
].map(require.resolve),
};

View File

@ -3,37 +3,41 @@ const jest = require('jest');
module.exports = {
collectCoverageFrom: [
'packages/strapi-admin/admin/src/**/**/*.js',
'!packages/strapi-admin/admin/src/*.js',
'!packages/strapi-admin/admin/src/utils/*.js',
'packages/strapi-plugin-*/admin/src/**/**/*.js',
'packages/strapi-plugin-*/admin/src/InjectedComponents/*.js',
'packages/strapi-plugin-*/admin/src/InjectedComponents/tests/*.js',
'!packages/strapi-plugin-content-type-builder/admin/src/components/TableList/*.js',
'!packages/strapi-plugin-content-type-builder/admin/src/components/TableListRow/*.js',
'!packages/strapi-plugin-*/admin/src/utils/*.js',
'!packages/strapi-plugin-*/admin/src/lifecycles/*.js',
'!packages/strapi-plugin-*/admin/src/**/**/tests/*.test.{js,jsx}',
],
globals: {
__webpack_public_path__: 'http://localhost:4000',
strapi: {},
BACKEND_URL: 'http://localhost:1337',
MODE: 'host',
PUBLIC_PATH: '/admin',
REMOTE_URL: '/',
NODE_ENV: 'test',
},
moduleDirectories: [
'node_modules',
'<rootDir>/packages/strapi-helper-plugin/node_modules',
'<rootDir>/packages/strapi-helper-plugin',
'<rootDir>/packages/strapi-helper-plugin/lib/src',
'<rootDir>/packages/strapi-admin/node_modules',
'<rootDir>/test/config/front',
],
moduleNameMapper: {
'.*\\.(css|less|styl|scss|sass)$':
'<rootDir>/packages/strapi-helper-plugin/lib/internals/mocks/cssModule.js',
'<rootDir>/test/config/front/mocks/cssModule.js',
'.*\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/packages/strapi-helper-plugin/lib/internals/mocks/image.js',
'<rootDir>/test/config/front/mocks/image.js',
},
rootDir: process.cwd(),
setupTestFrameworkScriptFile:
'<rootDir>/packages/strapi-helper-plugin/lib/internals/testing/test-bundler.js',
setupFilesAfterEnv: ['<rootDir>/test/config/front/test-bundler.js'],
setupFiles: [
'<rootDir>/packages/strapi-helper-plugin/node_modules/raf/polyfill',
'<rootDir>/packages/strapi-helper-plugin/lib/internals/testing/enzyme-setup.js',
'<rootDir>/packages/strapi-helper-plugin/lib/internals/testing/strapi.js',
'<rootDir>/test/config/front/enzyme-setup.js',
'<rootDir>/test/config/front/strapi.js',
],
testRegex: 'tests/.*\\.test\\.js$',
transform: {

View File

@ -1,29 +1,38 @@
{
"private": true,
"version": "3.0.0-alpha.25.2",
"dependencies": {},
"dependencies": {
"npm": "^6.9.0",
"uninstall": "0.0.0"
},
"devDependencies": {
"@babel/core": "^7.4.3",
"@babel/plugin-proposal-class-properties": "^7.4.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/polyfill": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"@babel/preset-react": "^7.0.0",
"assert": "~1.3.0",
"axios": "^0.18.0",
"babel-cli": "6.26.0",
"babel-core": "6.26.0",
"babel-eslint": "^6.1.2",
"babel-jest": "^24.1.0",
"babel-loader": "7.1.1",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-es2015-destructuring": "6.23.0",
"babel-plugin-transform-es2015-parameters": "6.24.1",
"babel-plugin-transform-object-rest-spread": "6.26.0",
"babel-plugin-transform-react-constant-elements": "6.23.0",
"babel-plugin-transform-react-inline-elements": "6.22.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.18",
"babel-polyfill": "6.26.0",
"babel-preset-env": "1.6.1",
"babel-preset-react": "6.24.1",
"babel-plugin-transform-es2015-destructuring": "^6.23.0",
"babel-plugin-transform-es2015-parameters": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-react-constant-elements": "^6.23.0",
"babel-plugin-transform-react-inline-elements": "^6.22.0",
"babel-plugin-transform-react-remove-prop-types": "^0.4.18",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"chalk": "^2.4.1",
"cross-env": "^5.2.0",
"cypress": "3.1.2",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
"eslint": "^4.19.1",
"eslint-plugin-babel": "^4.0.0",
"eslint-plugin-react": "^7.7.0",

View File

@ -61,7 +61,8 @@ import plugins from './plugins';
const initialState = {};
const store = configureStore(initialState, history);
const { dispatch } = store;
const MOUNT_NODE = document.getElementById('app');
const MOUNT_NODE =
document.getElementById('app') || document.createElement('div');
dispatch(getAppPluginsSucceeded(Object.keys(plugins)));
@ -165,7 +166,6 @@ const render = messages => {
ReactDOM.render(
<Provider store={store}>
<LanguageProvider messages={messages}>
{/* <ConnectedRouter history={history}> */}
<BrowserRouter basename={basename}>
<App store={store} />
</BrowserRouter>
@ -183,23 +183,25 @@ if (module.hot) {
});
}
// Chunked polyfill for browsers without Intl support
if (!window.Intl) {
new Promise(resolve => {
resolve(import('intl'));
})
.then(() =>
Promise.all([
import('intl/locale-data/jsonp/en.js'),
import('intl/locale-data/jsonp/de.js'),
]),
) // eslint-disable-line prettier/prettier
.then(() => render(translationMessages))
.catch(err => {
throw err;
});
} else {
render(translationMessages);
if (NODE_ENV !== 'test') {
// Chunked polyfill for browsers without Intl support
if (!window.Intl) {
new Promise(resolve => {
resolve(import('intl'));
})
.then(() =>
Promise.all([
import('intl/locale-data/jsonp/en.js'),
import('intl/locale-data/jsonp/de.js'),
]),
) // eslint-disable-line prettier/prettier
.then(() => render(translationMessages))
.catch(err => {
throw err;
});
} else {
render(translationMessages);
}
}
// @Pierre Burgy exporting dispatch for the notifications...

View File

@ -9,21 +9,20 @@ import { compose } from 'redux';
import {
disableGlobalOverlayBlocker,
enableGlobalOverlayBlocker,
} from 'actions/overlayBlocker';
updatePlugin,
} from '../../App/actions';
import LoadingIndicatorPage from 'components/LoadingIndicatorPage';
import OverlayBlocker from 'components/OverlayBlocker';
import { LoadingIndicatorPage, OverlayBlocker } from 'strapi-helper-plugin';
import injectReducer from '../../../utils/injectReducer';
import history from '../../../utils/history';
import configureStore from '../../../configureStore';
import { messages } from '../../../i18n';
// import { store } from '../../../createStore';
import messages from 'testUtils/commonTrads.json';
import Header from '../../../components/Header/index';
import Onboarding from '../../Onboarding';
import Logout from '../../../components/Logout';
import { updatePlugin } from '../../App/actions';
import localeToggleReducer from '../../LocaleToggle/reducer';
import {

View File

@ -48,9 +48,6 @@ function App(props) {
);
}
// App.contextTypes = {
// store: PropTypes.object,
// };
App.propTypes = {};
export default App;

View File

@ -3,7 +3,7 @@ import { shallow } from 'enzyme';
import { Route } from 'react-router-dom';
import AppLoader from '../../AppLoader';
import App from '../index';
import App from '../../App';
describe('<App />', () => {
it('should render the <AppLoader />', () => {

View File

@ -2,8 +2,6 @@ import { fromJS, List } from 'immutable';
import {
disableGlobalOverlayBlocker,
enableGlobalOverlayBlocker,
} from 'actions/overlayBlocker';
import {
freezeApp,
getAppPluginsSucceeded,
pluginDeleted,

View File

@ -1,6 +1,6 @@
import React from 'react';
import { shallow } from 'enzyme';
import BlockerComponent from 'components/BlockerComponent';
import { BlockerComponent } from 'strapi-helper-plugin';
import { PluginDispatcher } from '../index';
const BlockerComponent2 = () => <div>BlockerComponent</div>;
@ -56,7 +56,7 @@ describe('<PluginDispatcher />', () => {
expect(renderedComponent.find(BlockerComponent2)).toHaveLength(1);
});
it("Should return the plugin's mainComponent if all conditions are met", () => {
it('Should return the plugin\'s mainComponent if all conditions are met', () => {
const props = {
global: {
plugins: {

View File

@ -15,21 +15,36 @@ window.strapi = Object.assign(window.strapi || {}, {
injectSaga,
});
// module.exports = {
// documentation: require('../../../strapi-plugin-documentation/admin/dist/strapi-plugin-documentation.esm.js')
// .default,
// 'content-manager': require('../../../strapi-plugin-content-manager/admin/dist/strapi-plugin-content-manager.esm.js')
// .default,
// 'content-type-builder': require('../../../strapi-plugin-content-type-builder/admin/dist/strapi-plugin-content-type-builder.esm.js')
// .default,
// email: require('../../../strapi-plugin-email/admin/dist/strapi-plugin-email.esm.js')
// .default,
// 'users-permissions': require('../../../strapi-plugin-users-permissions/admin/dist/strapi-plugin-users-permissions.esm.js')
// .default,
// upload: require('../../../strapi-plugin-upload/admin/dist/strapi-plugin-upload.esm.js')
// .default,
// 'settings-manager':
// // 'settings-manager': require('../../../strapi-plugin-settings-manager/admin/src')
// require('../../../strapi-plugin-settings-manager/admin/dist/strapi-plugin-settings-manager.esm.js')
// .default,
// };
module.exports = {
documentation: require('../../../strapi-plugin-documentation/admin/dist/strapi-plugin-documentation.esm.js')
documentation: require('../../../strapi-plugin-documentation/admin/src')
.default,
'content-manager': require('../../../strapi-plugin-content-manager/admin/dist/strapi-plugin-content-manager.esm.js')
'content-manager': require('../../../strapi-plugin-content-manager/admin/src')
.default,
'content-type-builder': require('../../../strapi-plugin-content-type-builder/admin/dist/strapi-plugin-content-type-builder.esm.js')
'content-type-builder': require('../../../strapi-plugin-content-type-builder/admin/src')
.default,
email: require('../../../strapi-plugin-email/admin/dist/strapi-plugin-email.esm.js')
.default,
'users-permissions': require('../../../strapi-plugin-users-permissions/admin/dist/strapi-plugin-users-permissions.esm.js')
.default,
upload: require('../../../strapi-plugin-upload/admin/dist/strapi-plugin-upload.esm.js')
email: require('../../../strapi-plugin-email/admin/src').default,
'users-permissions': require('../../../strapi-plugin-users-permissions/admin/src')
.default,
upload: require('../../../strapi-plugin-upload/admin/src').default,
'settings-manager':
// 'settings-manager': require('../../../strapi-plugin-settings-manager/admin/src')
require('../../../strapi-plugin-settings-manager/admin/dist/strapi-plugin-settings-manager.esm.js')
.default,
require('../../../strapi-plugin-settings-manager/admin/src').default,
};

View File

@ -1,8 +1,8 @@
/**
*
* BlockerComponent
*
*/
*
* BlockerComponent
*
*/
import React from 'react';
import { FormattedMessage } from 'react-intl';
@ -12,8 +12,14 @@ import PropTypes from 'prop-types';
import styles from './styles.scss';
/* eslint-disable react/require-default-props */
function BlockerComponent({ blockerComponentTitle, blockerComponentDescription, blockerComponentIcon, blockerComponentContent = '' }) {
function BlockerComponent({
blockerComponentTitle,
blockerComponentDescription,
blockerComponentIcon,
blockerComponentContent = '',
}) {
let content;
console.log(blockerComponentContent);
switch (blockerComponentContent) {
case 'renderIde':
@ -50,7 +56,7 @@ const renderIde = () => (
<div className={styles.ide}>
<p>./config/environments/development/server.json</p>
<div>
<pre style={{ whiteSpace: 'pre-wrap'}}>
<pre style={{ whiteSpace: 'pre-wrap' }}>
<code>
&#123;
<br />
@ -58,7 +64,7 @@ const renderIde = () => (
<br />
&nbsp;"port": 1337,
<br />
<span style={{ color: '#006EE7'}}>
<span style={{ color: '#006EE7' }}>
&nbsp;"autoReload": &#123; enabled: true &#125;
</span>
<br />
@ -83,12 +89,25 @@ const renderIde = () => (
const renderButton = () => (
<div className={styles.buttonContainer}>
<a className={cn(styles.primary, 'btn')} href="http://strapi.io" target="_blank">Read the documentation</a>
<a
className={cn(styles.primary, 'btn')}
href="http://strapi.io"
target="_blank"
>
Read the documentation
</a>
</div>
);
BlockerComponent.defaultProps = {
blockerComponentContent: '',
blockerComponentDescription: 'app.utils.defaultMessage',
blockerComponentIcon: '',
blockerComponentTitle: 'app.utils.defaultMessage',
};
BlockerComponent.propTypes = {
blockerComponentContent: PropTypes.string.isRequired,
blockerComponentContent: PropTypes.string,
blockerComponentDescription: PropTypes.string.isRequired,
blockerComponentIcon: PropTypes.string.isRequired,
blockerComponentTitle: PropTypes.string.isRequired,

View File

@ -96,4 +96,4 @@
"npm": ">= 6.0.0"
},
"license": "MIT"
}
}

View File

@ -1,7 +1,7 @@
import React from 'react';
import { shallow } from 'enzyme';
import LiLink from 'components/LiLink';
import { LiLink } from 'strapi-helper-plugin';
import EditViewLink from '../EditViewLink';
describe('<EditViewLink />', () => {

View File

@ -6,10 +6,10 @@ import AttributeLi from '../index';
describe('<AttributeLi />', () => {
it('should not crash', () => {
shallow(<AttributeLi />);
shallow(<AttributeLi name="test" />);
});
it("should show the origin of the model if it's comming from a plugin", () => {
it('should show the origin of the model if it\'s comming from a plugin', () => {
const props = {
attributeInfos: {
configurable: false,
@ -31,7 +31,7 @@ describe('<AttributeLi />', () => {
expect(insideCompo.text()).toContain('users-permissions');
});
it("should not show the origin of the model if it's not comming from a plugin", () => {
it('should not show the origin of the model if it\'s not comming from a plugin', () => {
const props = {
attributeInfos: {
configurable: false,

View File

@ -14,7 +14,9 @@ import styles from './styles.scss';
function ButtonModalPrimary({ add, message, onClick, type }) {
/* istanbul ignore next */
// Ignoring the style condition is intended...
const className = add ? styles.buttonModalPrimaryAdd : styles.buttonModalPrimary;
const className = add
? styles.buttonModalPrimaryAdd
: styles.buttonModalPrimary;
return (
<Button className={className} onClick={onClick} type={type}>
@ -25,13 +27,14 @@ function ButtonModalPrimary({ add, message, onClick, type }) {
ButtonModalPrimary.defaultProps = {
add: false,
message: 'app.utils.defaultMessage',
onClick: () => {},
type: 'button',
};
ButtonModalPrimary.propTypes = {
add: PropTypes.bool,
message: PropTypes.string.isRequired,
message: PropTypes.string,
onClick: PropTypes.func,
type: PropTypes.string,
};

View File

@ -5,6 +5,6 @@ import ButtonModalSecondary from '../index';
describe('<ButtonModalSecondary />', () => {
it('should not crash', () => {
shallow(<ButtonModalSecondary />);
shallow(<ButtonModalSecondary onClick={jest.fn()} message="" />);
});
});

View File

@ -1,6 +1,6 @@
import React from 'react';
import InputNumber from 'components/InputNumberWithErrors';
import { InputNumberWithErrors as InputNumber } from 'strapi-helper-plugin';
import mountWithIntl from 'testUtils/mountWithIntl';
import formatMessagesWithPluginId from 'testUtils/formatMessages';
@ -11,7 +11,8 @@ import pluginTradsEn from '../../../translations/en.json';
import CustomCheckbox from '../index';
const messages = formatMessagesWithPluginId(pluginId, pluginTradsEn);
const renderComponent = (props = {}) => mountWithIntl(<CustomCheckbox {...props} />, messages);
const renderComponent = (props = {}) =>
mountWithIntl(<CustomCheckbox {...props} />, messages);
describe('<CustomCheckbox />', () => {
let props;
@ -57,7 +58,10 @@ describe('<CustomCheckbox />', () => {
it('should work', () => {
const wrapper = renderComponent(props);
const spyOnHandleChange = jest.spyOn(wrapper.instance(), 'handleChange');
const spyOnHandleChangeNumber = jest.spyOn(wrapper.instance(), 'handleInputNumberChange');
const spyOnHandleChangeNumber = jest.spyOn(
wrapper.instance(),
'handleInputNumberChange',
);
wrapper.instance().forceUpdate();
const input = wrapper.find('input').first();
@ -72,12 +76,16 @@ describe('<CustomCheckbox />', () => {
inputNumber.prop('onChange')({ target: { name: 'test', value: '1' } });
expect(props.onChange).toHaveBeenCalledWith({ target: { name: 'test', type: 'number', value: 1 } });
expect(props.onChange).toHaveBeenCalledWith({
target: { name: 'test', type: 'number', value: 1 },
});
expect(spyOnHandleChangeNumber).toHaveBeenCalled();
input.simulate('change', { target: { checked: false } });
expect(spyOnHandleChange).toHaveBeenCalled();
expect(props.onChange).toHaveBeenCalledWith({ target: { name: 'test', value: null } });
expect(props.onChange).toHaveBeenCalledWith({
target: { name: 'test', value: null },
});
wrapper.unmount();
});

View File

@ -1,8 +1,8 @@
/**
*
* LeftMenuLink
*
*/
*
* LeftMenuLink
*
*/
import React from 'react';
import PropTypes from 'prop-types';
@ -15,11 +15,14 @@ import Span from './Span';
import styles from './styles.scss';
function LeftMenuLink({ icon, isTemporary, name, source, to }) {
return (
<li className={styles.leftMenuLink}>
<NavLink className={styles.link} to={to} activeClassName={styles.linkActive}>
<NavLink
className={styles.link}
to={to}
activeClassName={styles.linkActive}
>
<div>
<i className={`fa ${icon}`} />
</div>
@ -27,7 +30,11 @@ function LeftMenuLink({ icon, isTemporary, name, source, to }) {
<span className={styles.linkSpan}>{startCase(name)}</span>
{!!source && (
<FormattedMessage id={`${pluginId}.from`}>
{msg => <Span>({msg}: {source})</Span>}
{msg => (
<Span>
({msg}: {source})
</Span>
)}
</FormattedMessage>
)}
{isTemporary && (

View File

@ -5,6 +5,6 @@ import WrapperModal from '../index';
describe('<WrapperModal />', () => {
it('should not crash', () => {
shallow(<WrapperModal />);
shallow(<WrapperModal isOpen onToggle={jest.fn()} />);
});
});

View File

@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
import mountWithIntl from 'testUtils/mountWithIntl';
import formatMessagesWithPluginId from 'testUtils/formatMessages';
import Input from 'components/InputsIndex';
import { InputsIndex as Input } from 'strapi-helper-plugin';
// This part is needed if you need to test the lifecycle of a container that contains FormattedMessages
import pluginId from '../../../pluginId';
@ -15,7 +15,8 @@ import AttributeForm from '../index';
const messages = formatMessagesWithPluginId(pluginId, pluginTradsEn);
const context = { emitEvent: jest.fn() };
const renderComponent = (props = {}) => mountWithIntl(<AttributeForm {...props} />, messages, context);
const renderComponent = (props = {}) =>
mountWithIntl(<AttributeForm {...props} />, messages, context);
describe('<AttributeForm />', () => {
let props;
@ -100,7 +101,7 @@ describe('<AttributeForm />', () => {
describe('instances', () => {
describe('GetFormErrors', () => {
it("should return an empty object if there is not field that contain the created field's name", () => {
it('should return an empty object if there is not field that contain the created field\'s name', () => {
props.modifiedData = { name: 'test' };
wrapper = renderComponent(props);
@ -110,12 +111,14 @@ describe('<AttributeForm />', () => {
expect(getFormErrors()).toEqual({});
});
it("should return an object with the input's name and an array of error if the name is empty", () => {
it('should return an object with the input\'s name and an array of error if the name is empty', () => {
wrapper = renderComponent(props);
const { getFormErrors } = wrapper.instance();
expect(getFormErrors()).toEqual({ name: [{ id: `${pluginId}.error.validation.required` }] });
expect(getFormErrors()).toEqual({
name: [{ id: `${pluginId}.error.validation.required` }],
});
});
it('should return a unique error if the name of the field is already taken', () => {
@ -126,7 +129,9 @@ describe('<AttributeForm />', () => {
const { getFormErrors } = wrapper.instance();
expect(getFormErrors()).toEqual({ name: [{ id: `${pluginId}.error.attribute.taken` }] });
expect(getFormErrors()).toEqual({
name: [{ id: `${pluginId}.error.attribute.taken` }],
});
});
it('should not return a unique error if the use is editing a field', () => {
@ -139,7 +144,9 @@ describe('<AttributeForm />', () => {
const { getFormErrors } = wrapper.instance();
expect(getFormErrors()).toEqual({ minLength: [{ id: `${pluginId}.error.validation.required` }] });
expect(getFormErrors()).toEqual({
minLength: [{ id: `${pluginId}.error.validation.required` }],
});
});
it('should not return a unique error if the use is editing a field', () => {
@ -189,9 +196,12 @@ describe('<AttributeForm />', () => {
handleGoTo('advanced');
expect(props.push).toHaveBeenCalledWith({
search: 'modalType=attributeForm&attributeType=string&settingType=advanced&actionType=create',
search:
'modalType=attributeForm&attributeType=string&settingType=advanced&actionType=create',
});
expect(context.emitEvent).toHaveBeenCalledWith('didSelectContentTypeFieldSettings');
expect(context.emitEvent).toHaveBeenCalledWith(
'didSelectContentTypeFieldSettings',
);
});
});
@ -281,7 +291,9 @@ describe('<AttributeForm />', () => {
handleSubmitAndContinue({ preventDefault: jest.fn() });
expect(props.onSubmitEdit).toHaveBeenCalledWith(true);
expect(context.emitEvent).toHaveBeenCalledWith('willAddMoreFieldToContentType');
expect(context.emitEvent).toHaveBeenCalledWith(
'willAddMoreFieldToContentType',
);
});
it('should not submit if thee form has an error', () => {

View File

@ -18,6 +18,7 @@ describe('CTB <HomePage />', () => {
canOpenModal: true,
createTempContentType: jest.fn(),
deleteModel: jest.fn(),
deleteTemporaryModel: jest.fn(),
models: [
{
icon: 'fa-cube',
@ -94,7 +95,9 @@ describe('CTB <HomePage />', () => {
const table = wrapper.find(TableList);
expect(table).toHaveLength(1);
expect(table.prop('title')).toEqual(`${pluginId}.table.contentType.title.plural`);
expect(table.prop('title')).toEqual(
`${pluginId}.table.contentType.title.plural`,
);
});
it('the tableList should have a singular title if there is more less 2 model', () => {
@ -114,7 +117,9 @@ describe('CTB <HomePage />', () => {
const table = wrapper.find(TableList);
expect(table).toHaveLength(1);
expect(table.prop('title')).toEqual(`${pluginId}.table.contentType.title.singular`);
expect(table.prop('title')).toEqual(
`${pluginId}.table.contentType.title.singular`,
);
});
});

View File

@ -3,7 +3,7 @@ import React from 'react';
import mountWithIntl from 'testUtils/mountWithIntl';
import formatMessagesWithPluginId from 'testUtils/formatMessages';
import Input from 'components/InputsIndex';
import { InputsIndex as Input } from 'strapi-helper-plugin';
import pluginId from '../../../pluginId';
import pluginTradsEn from '../../../translations/en.json';
@ -12,7 +12,8 @@ import ModelForm from '../index';
const messages = formatMessagesWithPluginId(pluginId, pluginTradsEn);
const context = { emitEvent: jest.fn() };
const renderComponent = (props = {}) => mountWithIntl(<ModelForm {...props} />, messages, context);
const renderComponent = (props = {}) =>
mountWithIntl(<ModelForm {...props} />, messages, context);
describe('<ModelForm />', () => {
let props;
@ -186,7 +187,8 @@ describe('<ModelForm />', () => {
expect(context.emitEvent).not.toHaveBeenCalled();
expect(props.push).toHaveBeenCalledWith({
search: 'modalType=model&settingType=base&actionType=edit&modelName=test',
search:
'modalType=model&settingType=base&actionType=edit&modelName=test',
});
});
@ -198,7 +200,9 @@ describe('<ModelForm />', () => {
handleGoTo('advanced');
expect(context.emitEvent).toHaveBeenCalledWith('didSelectContentTypeSettings');
expect(context.emitEvent).toHaveBeenCalledWith(
'didSelectContentTypeSettings',
);
expect(props.push).toHaveBeenCalledWith({
search: 'modalType=model&settingType=advanced&actionType=create',
});

View File

@ -7,7 +7,7 @@ import { Redirect, BrowserRouter } from 'react-router-dom';
import mountWithIntl from 'testUtils/mountWithIntl';
import formatMessagesWithPluginId from 'testUtils/formatMessages';
import EmptyAttributesBlock from 'components/EmptyAttributesBlock';
import { EmptyAttributesBlock } from 'strapi-helper-plugin';
import pluginId from '../../../pluginId';
import pluginTradsEn from '../../../translations/en.json';
@ -159,7 +159,7 @@ describe('<ModelPage />', () => {
expect(redirect.length).toEqual(1);
});
it("should display the EmptyAttributeBlock if the model's attributes are empty", () => {
it('should display the EmptyAttributeBlock if the model\'s attributes are empty', () => {
props.initialData.user.attributes = {};
props.modifiedData.user.attributes = {};
@ -168,13 +168,13 @@ describe('<ModelPage />', () => {
expect(wrapper.find(EmptyAttributesBlock)).toHaveLength(1);
});
it("should display the Block if the model's attributes are not empty", () => {
it('should display the Block if the model\'s attributes are not empty', () => {
const wrapper = shallow(<ModelPage {...props} />);
expect(wrapper.find(Block)).toHaveLength(1);
});
it("should display a singular text if the model's attributes relationship is one", () => {
it('should display a singular text if the model\'s attributes relationship is one', () => {
const wrapper = shallow(<ModelPage {...props} />);
expect(
@ -185,7 +185,7 @@ describe('<ModelPage />', () => {
).toContain('singular');
});
it("should display a plural text if the model's attributes relationships is more than one", () => {
it('should display a plural text if the model\'s attributes relationships is more than one', () => {
props.match.params.modelName = 'role&source=users-permissions';
props.match.path = `${basePath}/role&source=users-permissions`;
const wrapper = shallow(<ModelPage {...props} />);
@ -205,7 +205,10 @@ describe('<ModelPage />', () => {
props.match.path = `${basePath}/product`;
const wrapper = shallow(<ModelPage {...props} />);
const spyOnClick = jest.spyOn(wrapper.instance(), 'handleClickOpenModalChooseAttributes');
const spyOnClick = jest.spyOn(
wrapper.instance(),
'handleClickOpenModalChooseAttributes',
);
wrapper.instance().forceUpdate();
const onClick = wrapper.find(EmptyAttributesBlock).prop('onClick');
@ -224,7 +227,8 @@ describe('<ModelPage />', () => {
});
it('should return the newContentType if the url matches', () => {
(props.location.pathname = `${basePath}/test1`), (props.match.params.modelName = 'test1');
(props.location.pathname = `${basePath}/test1`),
(props.match.params.modelName = 'test1');
props.newContentType.name = 'test1';
const { getModel } = shallow(<ModelPage {...props} />).instance();
@ -234,31 +238,37 @@ describe('<ModelPage />', () => {
});
describe('GetModelAttributes', () => {
it("should return the model's attributes", () => {
const { getModelAttributes } = shallow(<ModelPage {...props} />).instance();
it('should return the model\'s attributes', () => {
const { getModelAttributes } = shallow(
<ModelPage {...props} />,
).instance();
expect(getModelAttributes()).toEqual(initialData.user.attributes);
});
});
describe('GetModelAttributesLength', () => {
it("should return the model's attributes length", () => {
const { getModelAttributesLength } = shallow(<ModelPage {...props} />).instance();
it('should return the model\'s attributes length', () => {
const { getModelAttributesLength } = shallow(
<ModelPage {...props} />,
).instance();
expect(getModelAttributesLength()).toEqual(8);
});
});
describe('GetModelDescription', () => {
it("should return the model's description field", () => {
const { getModelDescription } = shallow(<ModelPage {...props} />).instance();
it('should return the model\'s description field', () => {
const { getModelDescription } = shallow(
<ModelPage {...props} />,
).instance();
expect(getModelDescription()).toEqual('user model');
});
});
describe('GetModelName', () => {
it("should return the model's name field", () => {
it('should return the model\'s name field', () => {
const { getModelName } = shallow(<ModelPage {...props} />).instance();
expect(getModelName()).toEqual('user');
@ -267,7 +277,9 @@ describe('<ModelPage />', () => {
describe('GetModelsNumber', () => {
it('should return the number of models', () => {
const { getModelsNumber } = shallow(<ModelPage {...props} />).instance();
const { getModelsNumber } = shallow(
<ModelPage {...props} />,
).instance();
expect(getModelsNumber()).toEqual(5);
});
@ -275,7 +287,9 @@ describe('<ModelPage />', () => {
describe('GetModelRelationShips', () => {
it('should return the model`s relations', () => {
const { getModelRelationShips } = shallow(<ModelPage {...props} />).instance();
const { getModelRelationShips } = shallow(
<ModelPage {...props} />,
).instance();
const {
user: {
attributes: { role },
@ -291,7 +305,9 @@ describe('<ModelPage />', () => {
props.match.params.modelName = 'product';
props.match.path = `${basePath}/product`;
const { getModelRelationShipsLength } = shallow(<ModelPage {...props} />).instance();
const { getModelRelationShipsLength } = shallow(
<ModelPage {...props} />,
).instance();
expect(getModelRelationShipsLength()).toEqual(0);
});
@ -310,7 +326,9 @@ describe('<ModelPage />', () => {
props.modifiedData = { user: props.initialData.user };
props.models = [props.models[1]];
const { getSectionTitle } = shallow(<ModelPage {...props} />).instance();
const { getSectionTitle } = shallow(
<ModelPage {...props} />,
).instance();
expect(getSectionTitle()).toContain('singular');
});
@ -476,7 +494,9 @@ describe('<ModelPage /> lifecycle', () => {
await wait();
expect(context.emitEvent).toHaveBeenCalledWith('willEditFieldOfContentType');
expect(context.emitEvent).toHaveBeenCalledWith(
'willEditFieldOfContentType',
);
expect(props.history.push).toHaveBeenCalledWith({
search:
'modalType=attributeForm&attributeType=string&settingType=base&actionType=edit&attributeName=username',
@ -496,7 +516,9 @@ describe('<ModelPage /> lifecycle', () => {
await wait();
expect(context.emitEvent).toHaveBeenCalledWith('willEditFieldOfContentType');
expect(context.emitEvent).toHaveBeenCalledWith(
'willEditFieldOfContentType',
);
expect(props.history.push).toHaveBeenCalledWith({
search:
'modalType=attributeForm&attributeType=number&settingType=base&actionType=edit&attributeName=username',
@ -512,7 +534,10 @@ describe('<ModelPage /> lifecycle', () => {
const wrapper = topCompo.find(ModelPage);
const spyOnWait = jest.spyOn(wrapper.instance(), 'wait');
const spyOnDisplayNotification = jest.spyOn(wrapper.instance(), 'displayNotificationCTNotSaved');
const spyOnDisplayNotification = jest.spyOn(
wrapper.instance(),
'displayNotificationCTNotSaved',
);
const { handleClickEditModelMainInfos } = wrapper.instance();
handleClickEditModelMainInfos();
@ -521,7 +546,9 @@ describe('<ModelPage /> lifecycle', () => {
await wait();
expect(context.emitEvent).not.toHaveBeenCalledWith('willEditNameOfContentType');
expect(context.emitEvent).not.toHaveBeenCalledWith(
'willEditNameOfContentType',
);
expect(props.history.push).not.toHaveBeenCalled();
expect(spyOnDisplayNotification).toHaveBeenCalled();
});
@ -540,9 +567,12 @@ describe('<ModelPage /> lifecycle', () => {
await wait();
expect(context.emitEvent).toHaveBeenCalledWith('willEditNameOfContentType');
expect(context.emitEvent).toHaveBeenCalledWith(
'willEditNameOfContentType',
);
expect(props.history.push).toHaveBeenCalledWith({
search: 'modalType=model&settingType=base&actionType=edit&modelName=product',
search:
'modalType=model&settingType=base&actionType=edit&modelName=product',
});
});
});
@ -555,7 +585,10 @@ describe('<ModelPage /> lifecycle', () => {
const wrapper = topCompo.find(ModelPage);
const spyOnWait = jest.spyOn(wrapper.instance(), 'wait');
const spyOnDisplayNotification = jest.spyOn(wrapper.instance(), 'displayNotificationCTNotSaved');
const spyOnDisplayNotification = jest.spyOn(
wrapper.instance(),
'displayNotificationCTNotSaved',
);
const { handleClickOpenModalChooseAttributes } = wrapper.instance();
handleClickOpenModalChooseAttributes();
@ -582,7 +615,9 @@ describe('<ModelPage /> lifecycle', () => {
await wait();
expect(context.emitEvent).toHaveBeenCalledWith('willEditNameOfContentType');
expect(context.emitEvent).toHaveBeenCalledWith(
'willEditNameOfContentType',
);
expect(props.history.push).toHaveBeenCalledWith({
search: 'modalType=chooseAttributes',
});
@ -595,7 +630,10 @@ describe('<ModelPage /> lifecycle', () => {
topCompo = renderComponent(props);
const wrapper = topCompo.find(ModelPage);
const spyOnDisplayNotification = jest.spyOn(wrapper.instance(), 'displayNotificationCTNotSaved');
const spyOnDisplayNotification = jest.spyOn(
wrapper.instance(),
'displayNotificationCTNotSaved',
);
const { handleClickOpenModalCreateCT } = wrapper.instance();
handleClickOpenModalCreateCT();
@ -625,12 +663,17 @@ describe('<ModelPage /> lifecycle', () => {
topCompo = renderComponent(props);
const wrapper = topCompo.find(ModelPage);
const spyOnDisplayNotification = jest.spyOn(wrapper.instance(), 'displayNotificationCTNotSaved');
const spyOnDisplayNotification = jest.spyOn(
wrapper.instance(),
'displayNotificationCTNotSaved',
);
const { handleClickOnTrashIcon } = wrapper.instance();
handleClickOnTrashIcon('username');
expect(context.emitEvent).not.toHaveBeenCalledWith('willDeleteFieldOfContentType');
expect(context.emitEvent).not.toHaveBeenCalledWith(
'willDeleteFieldOfContentType',
);
expect(spyOnDisplayNotification).toHaveBeenCalled();
});
@ -643,8 +686,14 @@ describe('<ModelPage /> lifecycle', () => {
handleClickOnTrashIcon('username');
expect(wrapper.state()).toEqual({ showWarning: true, removePrompt: false, attrToDelete: 'username' });
expect(context.emitEvent).toHaveBeenCalledWith('willDeleteFieldOfContentType');
expect(wrapper.state()).toEqual({
showWarning: true,
removePrompt: false,
attrToDelete: 'username',
});
expect(context.emitEvent).toHaveBeenCalledWith(
'willDeleteFieldOfContentType',
);
});
});
});

View File

@ -1,9 +1,10 @@
import React from 'react';
import { shallow } from 'enzyme';
import NotFoundPage from '../index';
describe('<NotFoundPage />', () => {
it('should not crash', () => {
shallow(<NotFoundPage />);
shallow(<NotFoundPage history={{}} />);
});
});

View File

@ -54,7 +54,10 @@ describe('<RelationForm />', () => {
wrapper = renderComponent(props);
const compo = wrapper.find(RelationForm);
const spyOnRenderAdvancedSettings = jest.spyOn(compo.instance(), 'renderAdvancedSettings');
const spyOnRenderAdvancedSettings = jest.spyOn(
compo.instance(),
'renderAdvancedSettings',
);
compo.instance().forceUpdate();
expect(spyOnRenderAdvancedSettings).toHaveBeenCalled();
@ -131,7 +134,11 @@ describe('<RelationForm />', () => {
handleClick('strapi');
expect(props.onChangeRelationTarget).toHaveBeenLastCalledWith('strapi', 'test', false);
expect(props.onChangeRelationTarget).toHaveBeenLastCalledWith(
'strapi',
'test',
false,
);
});
it('should call the onChangeRelationTarget with the correct data (editing)', () => {
@ -143,7 +150,11 @@ describe('<RelationForm />', () => {
handleClick('strapi');
expect(props.onChangeRelationTarget).toHaveBeenLastCalledWith('strapi', 'test', true);
expect(props.onChangeRelationTarget).toHaveBeenLastCalledWith(
'strapi',
'test',
true,
);
});
});
});
@ -169,9 +180,12 @@ describe('<RelationForm />', () => {
handleGoTo('advanced');
expect(props.push).toHaveBeenCalledWith({
search: 'modalType=attributeForm&attributeType=relation&settingType=advanced&actionType=create',
search:
'modalType=attributeForm&attributeType=relation&settingType=advanced&actionType=create',
});
expect(context.emitEvent).toHaveBeenCalledWith('didSelectContentTypeFieldSettings');
expect(context.emitEvent).toHaveBeenCalledWith(
'didSelectContentTypeFieldSettings',
);
});
it('should add the keep the attribute name if the action is edit', () => {
@ -187,7 +201,9 @@ describe('<RelationForm />', () => {
search:
'modalType=attributeForm&attributeType=relation&settingType=advanced&actionType=edit&attributeName=test',
});
expect(context.emitEvent).toHaveBeenCalledWith('didSelectContentTypeFieldSettings');
expect(context.emitEvent).toHaveBeenCalledWith(
'didSelectContentTypeFieldSettings',
);
});
it('should not emit the event if the tab is base', () => {
@ -199,7 +215,8 @@ describe('<RelationForm />', () => {
handleGoTo('base');
expect(props.push).toHaveBeenCalledWith({
search: 'modalType=attributeForm&attributeType=relation&settingType=base&actionType=create',
search:
'modalType=attributeForm&attributeType=relation&settingType=base&actionType=create',
});
expect(context.emitEvent).not.toHaveBeenCalled();
});
@ -209,7 +226,7 @@ describe('<RelationForm />', () => {
it('should update the state and call the onCancel prop', () => {
wrapper = renderComponent(props);
const compo = wrapper.find(RelationForm);
compo.setState({ showForm: true, formErrors: { name: {} } });
compo.setState({ showForm: true, formErrors: { name: [] } });
expect(compo.state('showForm')).toBeTruthy();
@ -236,7 +253,13 @@ describe('<RelationForm />', () => {
handleOnOpened();
expect(compo.state('showForm')).toBeTruthy();
expect(props.initData).toHaveBeenCalledWith('test', false, 'test', '', false);
expect(props.initData).toHaveBeenCalledWith(
'test',
false,
'test',
'',
false,
);
});
it('should update the state and call the onCancel prop', () => {
@ -254,7 +277,13 @@ describe('<RelationForm />', () => {
handleOnOpened();
expect(compo.state('showForm')).toBeTruthy();
expect(props.initData).toHaveBeenCalledWith('strapi', false, undefined, 'test', true);
expect(props.initData).toHaveBeenCalledWith(
'strapi',
false,
undefined,
'test',
true,
);
});
});

View File

@ -95,4 +95,4 @@
"npm": ">= 6.0.0"
},
"license": "MIT"
}
}

View File

@ -113,4 +113,4 @@
"npm": ">= 5.3.0"
},
"license": "MIT"
}
}

View File

@ -89,4 +89,4 @@
"npm": ">= 6.0.0"
},
"license": "MIT"
}
}

View File

@ -92,4 +92,4 @@
"npm": ">= 6.0.0"
},
"license": "MIT"
}
}

View File

@ -84,4 +84,4 @@
"npm": ">= 6.0.0"
},
"license": "MIT"
}
}

View File

@ -93,4 +93,4 @@
"npm": ">= 6.0.0"
},
"license": "MIT"
}
}

View File

@ -11,14 +11,28 @@ const cmdEslint = template(
' --config ../../node_modules/strapi-lint/lib/internals/eslint/${conf}/.eslintrc.json ${params}',
);
const cmdFront = cmdEslint({ ignore: '/admin/build/', conf: 'front', params: 'admin' });
const cmdHelper = cmdEslint({ ignore: '/admin/build/', conf: 'front', params: 'lib/src' });
const cmdBack = cmdEslint({ ignore: '/admin', conf: 'back', params: 'controllers config services bin lib' });
const cmdFront = cmdEslint({
ignore: '/admin/build/',
conf: 'front',
params: 'admin',
});
const cmdHelper = cmdEslint({
ignore: '/admin/build/',
conf: 'front',
params: 'lib/src',
});
const cmdBack = cmdEslint({
ignore: '/admin',
conf: 'back',
params: 'controllers config services bin lib',
});
const watcher = (label, pckgName) => {
shell.echo(label);
shell.cd(pckgName);
const cmd = pckgName.includes('strapi-helper-plugin') ? cmdHelper : `${cmdFront} && ${cmdBack}`;
const cmd = pckgName.includes('strapi-helper-plugin')
? cmdHelper
: `${cmdFront} && ${cmdBack}`;
const data = shell.exec(cmd, { silent: true });
shell.echo(chalk(eslintErrorsFormatter(data.stdout)));
@ -31,6 +45,7 @@ const watcher = (label, pckgName) => {
};
const except = [
'babel.config.js',
'docs',
'jest.config.js',
'jest.config.front.js',
@ -45,7 +60,10 @@ const except = [
];
const changedDirs = [...changedFiles]
.filter(file => path.extname(file) === '.js' && !except.some(path => file.includes(path)))
.filter(
file =>
path.extname(file) === '.js' && !except.some(path => file.includes(path)),
)
.map(file => {
const directoryArray = file.split('/');
const toTake = directoryArray.length === 2 ? 1 : 2;

View File

@ -0,0 +1,8 @@
/* eslint-disable import/no-extraneous-dependencies */
const configure = require('enzyme').configure;
const Adapter = require('enzyme-adapter-react-16');
configure({
adapter: new Adapter(),
disableLifecycleMethods: false,
});

View File

@ -0,0 +1 @@
// module.exports = 'CSS_MODULE';

View File

@ -0,0 +1 @@
module.exports = 'IMAGE_MOCK';

View File

@ -0,0 +1,34 @@
/**
*
* Strapi
* This file allow to mock any key that is in the global strapi variable
*
*/
// Setup the strapi functioon global variable
const React = require('react');
const hoistNonReactStatics = require('hoist-non-react-statics');
const hoc = () => WrappedComponent => {
class HocInjector extends React.Component {
static WrappedComponent = WrappedComponent;
render() {
return <WrappedComponent {...this.props} />;
}
}
return hoistNonReactStatics(HocInjector, WrappedComponent);
};
global.strapi = {
injectReducer: hoc,
injectSaga: hoc,
notification: {
error: jest.fn(),
info: jest.fn(),
success: jest.fn(),
warning: jest.fn(),
},
};

View File

@ -0,0 +1,3 @@
// needed for regenerator-runtime
// (ES7 generator support is required by redux-saga)
require('@babel/polyfill');

View File

@ -0,0 +1,152 @@
{
"Analytics": "Analytics",
"Content Manager": "Content Manager",
"Content Type Builder": "Content Type Builder",
"Email": "Email",
"Files Upload": "Files Upload",
"HomePage.notification.newsLetter.success": "Successfully subscribed to the newsletter",
"New entry": "New entry",
"Password": "Password",
"Provider": "Provider",
"ResetPasswordToken": "Reset Password Token",
"Role": "Role",
"Roles & Permissions": "Roles & Permission",
"Settings Manager": "Settings Manager",
"Username": "Username",
"Users": "Users",
"Users & Permissions": "Users & Permissions",
"app.components.BlockLink.code": "Code examples",
"app.components.BlockLink.code.content": "Learn by testing real projects developed the community.",
"app.components.BlockLink.documentation": "Read the documentation",
"app.components.BlockLink.documentation.content": "Discover the concepts, reference guides and tutorials.",
"app.components.Button.cancel": "Cancel",
"app.components.Button.save": "Save",
"app.components.ComingSoonPage.comingSoon": "Coming soon",
"app.components.ComingSoonPage.featuresNotAvailable": "This feature is still under active development.",
"app.components.DownloadInfo.download": "Download in progress...",
"app.components.DownloadInfo.text": "This could take a minute. Thanks for your patience.",
"app.components.EmptyAttributes.title": "There are no fields yet",
"app.components.HomePage.button.blog": "SEE MORE ON THE BLOG",
"app.components.HomePage.button.quickStart": "START THE QUICK START TUTORIAL",
"app.components.HomePage.community": "Find the community on the web",
"app.components.HomePage.community.content": "Discuss with team members, contributors and developers on different channels.",
"app.components.HomePage.create": "Create your first Content Type",
"app.components.HomePage.createBlock.content.first": "The ",
"app.components.HomePage.createBlock.content.second": " plugin will help you to define the data structure of your models. If youre new here, we highly recommend you to follow our ",
"app.components.HomePage.createBlock.content.tutorial": " tutorial.",
"app.components.HomePage.cta": "CONFIRM",
"app.components.HomePage.newsLetter": "Subscribe to the newsletter to get in touch about Strapi",
"app.components.HomePage.support": "SUPPORT US",
"app.components.HomePage.support.content": "By buying the T-shirt, it will allow us to continue our work on the project to give you the best possible experience!",
"app.components.HomePage.support.link": "GET YOUR T-SHIRT NOW",
"app.components.HomePage.welcome": "Welcome on board!",
"app.components.HomePage.welcome.again": "Welcome ",
"app.components.HomePage.welcomeBlock.content": "We are happy to have you as one of community member. We are constantly looking for feedback so feel free to send us DM on ",
"app.components.HomePage.welcomeBlock.content.again": "We hope you are making progress on your project... Feel free to read the latest new about Strapi. We are giving our best to improve the product based on your feedback.",
"app.components.HomePage.welcomeBlock.content.issues": "issues.",
"app.components.HomePage.welcomeBlock.content.raise": " or raise ",
"app.components.ImgPreview.hint": "Drag & drop your file into this area or {browse} for a file to upload",
"app.components.ImgPreview.hint.browse": "browse",
"app.components.InputFile.newFile": "Add new file",
"app.components.InputFileDetails.open": "Open in a new tab",
"app.components.InputFileDetails.originalName": "Original name:",
"app.components.InputFileDetails.remove": "Remove this file",
"app.components.InputFileDetails.size": "Size:",
"app.components.InstallPluginPage.Download.title": "Downloading...",
"app.components.InstallPluginPage.Download.description": "It might take a few seconds to download and install the plugin.",
"app.components.InstallPluginPage.InputSearch.label": " ",
"app.components.InstallPluginPage.InputSearch.placeholder": "Search for a plugin... (ex: authentication)",
"app.components.InstallPluginPage.description": "Extend your app effortlessly.",
"app.components.InstallPluginPage.helmet": "Marketplace - Plugins",
"app.components.InstallPluginPage.plugin.support-us.description": "Support us by buying the Strapi T-shirt. That will allow us to keep working on the project and try giving you the best possible experience!",
"app.components.InstallPluginPage.title": "Marketplace - Plugins",
"app.components.InstallPluginPopup.downloads": "download",
"app.components.InstallPluginPopup.navLink.avis": "avis",
"app.components.InstallPluginPopup.navLink.changelog": "changelog",
"app.components.InstallPluginPopup.navLink.description": "Description",
"app.components.InstallPluginPopup.navLink.faq": "faq",
"app.components.InstallPluginPopup.navLink.screenshots": "Screenshots",
"app.components.InstallPluginPopup.noDescription": "No description available",
"app.components.LeftMenuFooter.documentation": "Documentation",
"app.components.LeftMenuFooter.help": "Help",
"app.components.LeftMenuFooter.poweredBy": "Powered by ",
"app.components.LeftMenuLinkContainer.configuration": "Configurations",
"app.components.LeftMenuLinkContainer.general": "General",
"app.components.LeftMenuLinkContainer.installNewPlugin": "Marketplace",
"app.components.LeftMenuLinkContainer.listPlugins": "Plugins",
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "No plugins installed yet",
"app.components.LeftMenuLinkContainer.plugins": "Plugins",
"app.components.ListPluginsPage.description": "List of the installed plugins in the project.",
"app.components.ListPluginsPage.helmet.title": "List plugins",
"app.components.ListPluginsPage.title": "Plugins",
"app.components.Logout.profile": "Profile",
"app.components.Logout.logout": "Logout",
"app.components.NotFoundPage.back": "Back to homepage",
"app.components.NotFoundPage.description": "Not Found",
"app.components.Official": "Official",
"app.components.Onboarding.label.completed": "% completed",
"app.components.Onboarding.title": "Get Started Videos",
"app.components.PluginCard.Button.label.download": "Download",
"app.components.PluginCard.Button.label.install": "Already installed",
"app.components.PluginCard.Button.label.support": "Support us",
"app.components.PluginCard.compatible": "Compatible with your app",
"app.components.PluginCard.compatibleCommunity": "Compatible with the community",
"app.components.PluginCard.more-details": "More details",
"app.components.PluginCard.price.free": "Free",
"app.components.PluginCard.settings": "Settings",
"app.components.listPlugins.button": "Add New Plugin",
"app.components.listPlugins.title.none": "No plugins installed",
"app.components.listPlugins.title.plural": "{number} plugins are installed",
"app.components.listPlugins.title.singular": "{number} plugin is installed",
"app.components.listPluginsPage.deletePlugin.error": "An error occurred while uninstalling the plugin",
"app.utils.SelectOption.defaultMessage": " ",
"app.utils.defaultMessage": " ",
"app.utils.placeholder.defaultMessage": " ",
"components.AutoReloadBlocker.description": "Open the following file and enable the feature.",
"components.AutoReloadBlocker.header": "Reload feature is required for this plugin.",
"components.ErrorBoundary.title": "Something went wrong...",
"components.Input.error.attribute.key.taken": "This value already exists",
"components.Input.error.attribute.sameKeyAndName": "Can't be equal",
"components.Input.error.attribute.taken": "This field name already exists",
"components.Input.error.contentTypeName.taken": "This name already exists",
"components.Input.error.custom-error": "{errorMessage} ",
"components.Input.error.validation.email": "This is not an email",
"components.Input.error.validation.json": "This doesn't match the JSON format",
"components.Input.error.validation.max": "The value is too high.",
"components.Input.error.validation.maxLength": "The value is too long.",
"components.Input.error.validation.min": "The value is too low.",
"components.Input.error.validation.minLength": "The value is too short.",
"components.Input.error.validation.minSupMax": "Can't be superior",
"components.Input.error.validation.regex": "The value not match the regex.",
"components.Input.error.validation.required": "This value is required.",
"components.ListRow.empty": "There is no data to be shown.",
"components.OverlayBlocker.description": "You're using a feature that needs the server to restart. Please wait until the server is up.",
"components.OverlayBlocker.description.serverError": "The server should have restarted, please check your logs in the terminal.",
"components.OverlayBlocker.title": "Waiting for restart...",
"components.OverlayBlocker.title.serverError": "The restart takes longer than expected",
"components.PageFooter.select": "entries per page",
"components.ProductionBlocker.description": "For safety purposes we have to disable this plugin in other environments.",
"components.ProductionBlocker.header": "This plugin is only available in development.",
"components.Wysiwyg.ToggleMode.markdown": "Switch to markdown",
"components.Wysiwyg.ToggleMode.preview": "Switch to preview",
"components.Wysiwyg.collapse": "Collapse",
"components.Wysiwyg.selectOptions.H1": "Title H1",
"components.Wysiwyg.selectOptions.H2": "Title H2",
"components.Wysiwyg.selectOptions.H3": "Title H3",
"components.Wysiwyg.selectOptions.H4": "Title H4",
"components.Wysiwyg.selectOptions.H5": "Title H5",
"components.Wysiwyg.selectOptions.H6": "Title H6",
"components.Wysiwyg.selectOptions.title": "Add a title",
"components.WysiwygBottomControls.charactersIndicators": "characters",
"components.WysiwygBottomControls.fullscreen": "Expand",
"components.WysiwygBottomControls.uploadFiles": "Drag & drop files, paste from the clipboard or {browse}.",
"components.WysiwygBottomControls.uploadFiles.browse": "select them",
"components.popUpWarning.button.cancel": "Cancel",
"components.popUpWarning.button.confirm": "Confirm",
"components.popUpWarning.message": "Are you sure you want to delete this?",
"components.popUpWarning.title": "Please confirm",
"notification.error": "An error occurred",
"notification.error.layout": "Couldn't retrieve the layout",
"request.error.model.unknown": "This model doesn't exist",
"app.utils.delete": "Delete"
}

View File

@ -0,0 +1,11 @@
import commonTrads from './commonTrads.json';
const formatMessagesWithPluginId = (pluginId, messages) => {
return Object.keys(messages).reduce((acc, current) => {
acc[`${pluginId}.${current}`] = messages[current];
return acc;
}, commonTrads);
};
export default formatMessagesWithPluginId;

View File

@ -0,0 +1,19 @@
import React from 'react';
import { mount } from 'enzyme';
import PropTypes from 'prop-types';
import { IntlProvider, intlShape } from 'react-intl';
const mountWithIntl = (componentToMount, pluginTrads, context = {}) => {
const intlProvider = new IntlProvider(
{ locale: 'en', messages: pluginTrads },
{},
);
const { intl } = intlProvider.getChildContext();
return mount(React.cloneElement(componentToMount, { intl }), {
context: { intl, ...context },
childContextTypes: { intl: intlShape, emitEvent: PropTypes.func },
});
};
export default mountWithIntl;