将react-intl对象注入已安装的酶组件中以进行测试
解决了!向下滚动以获取答案
在我们的组件测试中,我们需要它们能够访问react-intl
上下文。问题在于,我们正在安装单个组件(带有Enzyme的组件mount()
)而没有它们的<IntlProvider
/>父包装。可以通过以下方式解决此问题:将提供程序包装在一起,然后root
将IntlProvider
实例指向实例,而不要指向CustomComponent
。
该测试与阵营-国际:enzyme文档仍然是空的。
class CustomComponent extends Component { state = {
foo: 'bar'
}
render() {
return (
<div>
<FormattedMessage id="world.hello" defaultMessage="Hello World!" />
</div>
);
}
}
(酶+摩卡咖啡+柴)
// This is how we mount components normally with Enzymeconst wrapper = mount(
<CustomComponent
params={params}
/>
);
expect( wrapper.state('foo') ).to.equal('bar');
但是,由于我们的组件FormattedMessage
用作react-intl
库的一部分,因此在运行上述代码时会出现此错误:
Uncaught Invariant Violation: [React Intl] Could not find required
intlobject. <IntlProvider> needs to exist in the component ancestry.
const wrapper = mount( <IntlProvider locale="en">
<CustomComponent
params={params}
/>
</IntlProvider>
);
这提供CustomComponent
了intl
它要求的上下文。但是,在尝试测试诸如此类的断言时:
expect( wrapper.state('foo') ).to.equal('bar');
引发以下异常:
AssertionError: expected undefined to equal ''
这当然是因为它试图读取IntlProvider
而不是我们的状态CustomComponent
。
回答:
我尝试了以下无济于事:
const wrapper = mount( <IntlProvider locale="en">
<CustomComponent
params={params}
/>
</IntlProvider>
);
// Below cases have all individually been tried to call `.state('foo')` on:
// expect( component.state('foo') ).to.equal('bar');
const component = wrapper.childAt(0);
> Error: ReactWrapper::state() can only be called on the root
const component = wrapper.children();
> Error: ReactWrapper::state() can only be called on the root
const component = wrapper.children();
component.root = component;
> TypeError: Cannot read property 'getInstance' of null
现在的问题是:
?
回答:
我创建了一个辅助功能来修补现有的酶mount()
和shallow()
功能。现在,我们在所有使用React Intl组件的测试中都使用这些辅助方法。
您可以在这里找到要点:https://gist.github.com/mirague/c05f4da0d781a9b339b501f1d5d33c37
为了保持数据的可访问性,以下是简而言之的代码:
/** * 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,
* English-locale intl context around them.
*/
import React from 'react';
import { IntlProvider, intlShape } from 'react-intl';
import { mount, shallow } from 'enzyme';
const messages = require('../locales/en'); // en.json
const intlProvider = new IntlProvider({ locale: 'en', messages }, {});
const { intl } = intlProvider.getChildContext();
/**
* When using React-Intl `injectIntl` on components, props.intl is required.
*/
function nodeWithIntlProp(node) {
return React.cloneElement(node, { intl });
}
export default {
shallowWithIntl(node) {
return shallow(nodeWithIntlProp(node), { context: { intl } });
},
mountWithIntl(node) {
return mount(nodeWithIntlProp(node), {
context: { intl },
childContextTypes: { intl: intlShape }
});
}
};
class CustomComponent extends Component { state = {
foo: 'bar'
}
render() {
return (
<div>
<FormattedMessage id="world.hello" defaultMessage="Hello World!" />
</div>
);
}
}
import { mountWithIntl } from 'helpers/intl-test';const wrapper = mountWithIntl(
<CustomComponent />
);
expect(wrapper.state('foo')).to.equal('bar'); // OK
expect(wrapper.text()).to.equal('Hello World!'); // OK
以上是 将react-intl对象注入已安装的酶组件中以进行测试 的全部内容, 来源链接: utcz.com/qa/414893.html