Skip to content

Commit

Permalink
Fix/react intl testing helper functions (#24527) (#24975)
Browse files Browse the repository at this point in the history
update testing helper functions for react-intl

now we use real intl object passed by IntlProvider via context instead of mocking intl object.
so now data(strings, JSX) passed to FormattedMessage component via values are compiled and
are inserted in the output of FormattedMessage component
  • Loading branch information
pavel06081991 authored Nov 1, 2018
1 parent 1dd6dba commit ce35524
Show file tree
Hide file tree
Showing 10 changed files with 306 additions and 487 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Object {
data-test-subj="createIndexPatternStep1Header"
errors={
Array [
"A {indexPatternName} cannot contain spaces or the characters: {characterList}",
"A name cannot contain spaces or the characters: \\\\, /, ?, \\", <, >, |",
]
}
goToNextStep={[Function]}
Expand All @@ -16,48 +16,6 @@ Object {
onQueryChanged={[Function]}
query="?"
/>,
"i18n": Array [
Array [
Object {
"defaultMessage": "A {indexPatternName} cannot contain spaces or the characters: {characterList}",
"id": "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage",
},
Object {
"characterList": "\\\\, /, ?, \\", <, >, |",
"indexPatternName": "name",
},
],
Array [
Object {
"defaultMessage": "A {indexPatternName} cannot contain spaces or the characters: {characterList}",
"id": "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage",
},
Object {
"characterList": "\\\\, /, ?, \\", <, >, |",
"indexPatternName": "name",
},
],
Array [
Object {
"defaultMessage": "A {indexPatternName} cannot contain spaces or the characters: {characterList}",
"id": "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage",
},
Object {
"characterList": "\\\\, /, ?, \\", <, >, |",
"indexPatternName": "name",
},
],
Array [
Object {
"defaultMessage": "A {indexPatternName} cannot contain spaces or the characters: {characterList}",
"id": "kbn.management.createIndexPattern.step.invalidCharactersErrorMessage",
},
Object {
"characterList": "\\\\, /, ?, \\", <, >, |",
"indexPatternName": "name",
},
],
],
}
`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import React from 'react';
import { StepIndexPatternComponent } from '../step_index_pattern';
import { shallowWithIntl, intl } from 'test_utils/enzyme_helpers';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { Header } from '../components/header';

jest.mock('../../../lib/ensure_minimum_time', () => ({
Expand Down Expand Up @@ -79,8 +79,6 @@ const createComponent = props => {
};

describe('StepIndexPattern', () => {
afterEach(() => intl.formatMessage.mockClear());

it('renders the loading state', () => {
const component = createComponent();
component.setState({ isLoadingIndices: true });
Expand Down Expand Up @@ -109,7 +107,6 @@ describe('StepIndexPattern', () => {
component.update();
expect({
component: component.find('[data-test-subj="createIndexPatternStep1Header"]'),
i18n: intl.formatMessage.mock.calls,
}).toMatchSnapshot();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ exports[`ScriptedFieldsTable should show a delete modal 1`] = `
confirmButtonText="Delete"
onCancel={[Function]}
onConfirm={[Function]}
title="Delete scripted field '{fieldName}'?"
title="Delete scripted field 'ScriptedField'?"
/>
</eui-overlay-mask>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ exports[`Field for array setting should render user value if there is user value
<span>
<span>
<EuiLink
aria-label="Reset {ariaName} to default"
aria-label="Reset array test setting to default"
color="primary"
data-test-subj="advancedSetting-resetField-array:test:setting"
onClick={[Function]}
Expand Down Expand Up @@ -712,7 +712,7 @@ exports[`Field for boolean setting should render user value if there is user val
<span>
<span>
<EuiLink
aria-label="Reset {ariaName} to default"
aria-label="Reset boolean test setting to default"
color="primary"
data-test-subj="advancedSetting-resetField-boolean:test:setting"
onClick={[Function]}
Expand Down Expand Up @@ -1082,7 +1082,7 @@ exports[`Field for image setting should render user value if there is user value
<span>
<span>
<EuiLink
aria-label="Reset {ariaName} to default"
aria-label="Reset image test setting to default"
color="primary"
data-test-subj="advancedSetting-resetField-image:test:setting"
onClick={[Function]}
Expand All @@ -1098,7 +1098,7 @@ exports[`Field for image setting should render user value if there is user value
</span>
<span>
<EuiLink
aria-label="Change {ariaName}"
aria-label="Change image test setting"
color="primary"
data-test-subj="advancedSetting-changeImage-image:test:setting"
onClick={[Function]}
Expand Down Expand Up @@ -1440,7 +1440,7 @@ exports[`Field for json setting should render default value if there is no user
<span>
<span>
<EuiLink
aria-label="Reset {ariaName} to default"
aria-label="Reset json test setting to default"
color="primary"
data-test-subj="advancedSetting-resetField-json:test:setting"
onClick={[Function]}
Expand Down Expand Up @@ -1575,7 +1575,7 @@ exports[`Field for json setting should render user value if there is user value
<span>
<span>
<EuiLink
aria-label="Reset {ariaName} to default"
aria-label="Reset json test setting to default"
color="primary"
data-test-subj="advancedSetting-resetField-json:test:setting"
onClick={[Function]}
Expand Down Expand Up @@ -2018,7 +2018,7 @@ exports[`Field for markdown setting should render user value if there is user va
<span>
<span>
<EuiLink
aria-label="Reset {ariaName} to default"
aria-label="Reset markdown test setting to default"
color="primary"
data-test-subj="advancedSetting-resetField-markdown:test:setting"
onClick={[Function]}
Expand Down Expand Up @@ -2413,7 +2413,7 @@ exports[`Field for number setting should render user value if there is user valu
<span>
<span>
<EuiLink
aria-label="Reset {ariaName} to default"
aria-label="Reset number test setting to default"
color="primary"
data-test-subj="advancedSetting-resetField-number:test:setting"
onClick={[Function]}
Expand Down Expand Up @@ -2843,7 +2843,7 @@ exports[`Field for select setting should render user value if there is user valu
<span>
<span>
<EuiLink
aria-label="Reset {ariaName} to default"
aria-label="Reset select test setting to default"
color="primary"
data-test-subj="advancedSetting-resetField-select:test:setting"
onClick={[Function]}
Expand Down Expand Up @@ -3239,7 +3239,7 @@ exports[`Field for string setting should render user value if there is user valu
<span>
<span>
<EuiLink
aria-label="Reset {ariaName} to default"
aria-label="Reset string test setting to default"
color="primary"
data-test-subj="advancedSetting-resetField-string:test:setting"
onClick={[Function]}
Expand Down
103 changes: 61 additions & 42 deletions src/test_utils/public/enzyme_helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,67 +17,86 @@
* under the License.
*/

import PropTypes from 'prop-types';
/**
* Components using the react-intl module require access to the intl context.
* This is not available when mounting single components in Enzyme.
* These helper functions aim to address that and wrap a valid,
* intl context around them.
*/

import React from 'react';
import { shallow, mount } from 'enzyme';
import { intl } from './mocks/intl';
import { I18nProvider, intlShape } from '@kbn/i18n/react';
import { mount, shallow, render } from 'enzyme';

// Use fake component to extract `intl` property to use in tests.
const { intl } = mount(<I18nProvider><br /></I18nProvider>)
.find('IntlProvider').instance().getChildContext();

function getOptions(context = {}, childContextTypes = {}, props = []) {
return {
context: {
...context,
intl,
},
childContextTypes: {
...childContextTypes,
intl: intlShape,
},
...props,
};
}

/**
* When using React-Intl `injectIntl` on components, props.intl is required.
*/
function nodeWithIntlProp(node) {
return React.cloneElement(node, { intl });
}

/**
* Creates the wrapper instance using shallow with provided intl object into context
*
* @param node The React element or cheerio wrapper
* @param options properties to pass into shallow wrapper
* @param node The React element or cheerio wrapper
* @param options properties to pass into shallow wrapper
* @return The wrapper instance around the rendered output with intl object in context
*/
export function shallowWithIntl(node, { context = {}, childContextTypes = {}, ...props } = {}) {
const clonedNode = cloneNode(node);
export function shallowWithIntl(node, { context, childContextTypes, ...props } = {}) {
const options = getOptions(context, childContextTypes, props);

if (React.isValidElement(node)) {
return shallow(clonedNode, options);
}

return clonedNode.shallow(options);
return shallow(
nodeWithIntlProp(node),
options,
);
}

/**
* Creates the wrapper instance using mount with provided intl object into context
*
* @param node The React element or cheerio wrapper
* @param options properties to pass into mount wrapper
* @param node The React element or cheerio wrapper
* @param options properties to pass into mount wrapper
* @return The wrapper instance around the rendered output with intl object in context
*/
export function mountWithIntl(node, { context = {}, childContextTypes = {}, ...props } = {}) {
const clonedNode = cloneNode(node);
export function mountWithIntl(node, { context, childContextTypes, ...props } = {}) {
const options = getOptions(context, childContextTypes, props);

if (React.isValidElement(node)) {
return mount(clonedNode, options);
}

return clonedNode.mount(options);
return mount(
nodeWithIntlProp(node),
options,
);
}

export { intl };

function cloneNode(node) {
if (!node) {
throw new Error(`First argument should be cheerio object or React element, not ${node}`);
}

return React.cloneElement(node, { intl });
}
/**
* Creates the wrapper instance using render with provided intl object into context
*
* @param node The React element or cheerio wrapper
* @param options properties to pass into render wrapper
* @return The wrapper instance around the rendered output with intl object in context
*/
export function renderWithIntl(node, { context, childContextTypes, ...props } = {}) {
const options = getOptions(context, childContextTypes, props);

function getOptions(context, childContextTypes, props) {
return {
context: {
...context,
intl,
},
childContextTypes: {
...childContextTypes,
intl: PropTypes.any,
},
...props,
};
return render(
nodeWithIntlProp(node),
options,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ exports[`LabelTemplateFlyout should render normally 1`] = `
Array [
Object {
"input": 1234,
"labelTemplate": "User #{value}",
"labelTemplate": "User #{{value}}",
"output": "<a href=\\"http://company.net/profiles?user_id=1234\\">User #1234</a>",
"urlTemplate": "http://company.net/profiles?user_id={{value}}",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,51 +90,51 @@ Array [

exports[`index table should show the right context menu options when more than one closed index is selected 1`] = `
Array [
"Open {entity}",
"Delete {entity}",
"Open indices",
"Delete indices",
]
`;

exports[`index table should show the right context menu options when more than one open index is selected 1`] = `
Array [
"Close {entity}",
"Force merge {entity}",
"Refresh {entity}",
"Clear {entity} cache",
"Flush {entity}",
"Delete {entity}",
"Close indices",
"Force merge indices",
"Refresh indices",
"Clear indices cache",
"Flush indices",
"Delete indices",
]
`;

exports[`index table should show the right context menu options when one index is selected and closed 1`] = `
Array [
"Show {entity} settings",
"Show {entity} mapping",
"Edit {entity} settings",
"Open {entity}",
"Delete {entity}",
"Show index settings",
"Show index mapping",
"Edit index settings",
"Open index",
"Delete index",
]
`;

exports[`index table should show the right context menu options when one index is selected and open 1`] = `
Array [
"Show {entity} settings",
"Show {entity} mapping",
"Show {entity} stats",
"Edit {entity} settings",
"Close {entity}",
"Force merge {entity}",
"Refresh {entity}",
"Clear {entity} cache",
"Flush {entity}",
"Delete {entity}",
"Show index settings",
"Show index mapping",
"Show index stats",
"Edit index settings",
"Close index",
"Force merge index",
"Refresh index",
"Clear index cache",
"Flush index",
"Delete index",
]
`;

exports[`index table should show the right context menu options when one open and one closed index is selected 1`] = `
Array [
"Open {entity}",
"Delete {entity}",
"Open indices",
"Delete indices",
]
`;

Expand Down
Loading

0 comments on commit ce35524

Please sign in to comment.