I am trying to assert against an element that is provided as a prop to a component.
e.g.
function ComponentUnderTest() {
const foo = <span>đŸ‘‹</span>
return <Bob something={foo} />
}
I have tried doing something like:
shallow(<ComponentUnderTest />)
.prop(‘something’)
.matchesElement(<span>đŸ‘‹</span>)
But I get an error similar to:
(0 , _enzyme.shallow)(...).prop(...).matchesElement is not a function
It is like I need to lift the something prop value into the enzyme wrapper API.
Any ideas on how I could do this and avoid having to tap into the element itself.
Ria's comment above seems correct to me. .prop(‘something’) will return the property value for the "something" prop. This property value is not going to be a ShallowWrapper instance (you can check what it actually is by printing .prop(‘something’) to the console). Therefore, you get the normal JavaScript error you get when trying to call a function that does not exist (since .prop(‘something’).matchesElement will be undefined).
So you can wrap your prop with shallow to initialize Shallow Wrapper and assert using its methods like
shallow(
shallow(<ComponentUnderTest />).prop(‘something’)
)
.matchesElement(<span>đŸ‘‹</span>)
Related
Using react-select v2, I want to show and focus on the Select element when the user hits a certain key. Following are some things I've tried or paths I've gone down.
When I set a ref to the Select element and try to call .focus on it, it says no focus function is found. Perhaps I should somehow get a child element of it and then call focus on that?
There doesn't seem to be any prop I can pass that will trigger a focus function. There is an openOnFocus but not a focusOnOpen. The only thing I can think of would be to enable autoFocus and then somehow trigger a remount but there doesn't seem to be a simple way to do this and it feels hacky. Alternatively, I could enable just create the Select component each time the key is pressed instead of showing it, then unmount it instead of hiding it.
How can I properly get the react-select element to gain focus when I want it to?
I'm using a wrapper component around my component. Here's the render method for my wrapper:
render() {
return (
<Select
options={this.props.options}
value={this.state.value}
ref={this.selectRef}
/>
);
}
And here's where I'm calling that wrapper:
<Wrapper
options={this.props.labelOptions}
ref={this.wrapperRef}
/>
I then try calling focus using either this.dropdownNode.focus() or this.dropdownNode.current.focus() and both say no focus method is found.
Because you're wrapping the Select component, you can't call Select's .focus() function from the ref you're giving to the wrapper. Since ref is a special kind of prop, the ref for that wrapper is only referring to Wrapper itself, not the component it wraps (Select).
To access the actual Select component's ref, you have to pass a ref down to it as a prop with a different, non-magic name, like innerRef (react-select code actually gives a good example of this as it's accessing the actual input element and focusing on that).
Here's the change that fixed it. Here is the wrapper component where Select is actually used (and it's taking in the ref passed to it):
render() {
return (
<Select
options={this.props.options}
value={this.state.value}
ref={this.props.innerRef}
/>
);
}
And here's the component that's calling that wrapper. In the constructor I'm creating the ref with this.selectRef = React.createRef() then I pass it in as a prop in this render method:
<Wrapper
options={this.props.labelOptions}
innerRef={this.selectRef}
/>
Then I can call focus on the Select component itself by running this.selectRef.current.focus() anywhere I want to.
Notes: Thanks to BoyWithSilverWings answer. This question pertains to React 16.3. There is also a new React.ForwardRefs method but this way seems simpler to me.
I have AccountSelection, that renders AccountSelectionModal.
I want to do mount in order to test some aspects of the user interaction:
const wrapper = mount(<AccountSelection {...accountSelectionComponentParams} />);
However I would like to mock AccountSelectionModal - I don't need it (and it is also connected component and I don't want to use store in my tests).
When I mock it with jest.mock('../AccountSelectionModal', () => 'AccountSelectionModal');
I start to get plenty of warnings:
Warning: <AccountSelectionModal /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
console.error node_modules\fbjs\lib\warning.js:33
and
Warning: The tag <AccountSelectionModal> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
or
Warning: Unknown event handler property `onHide`. It will be ignored.
or
React does not recognize the `selectedAccountId` prop on a DOM element. If you intentionally want it to appear in the DOM as
a custom attribute, spell it as lowercase `selectedaccountid` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
All warnings come from props that are set on AccountSelectionModal.
How can I mock properly AccountSelectionModal
The second argument that you pass to mock is a function that returns whatever you want it to return, and since you want to mock a component, then this function should return a valid react component (now it's returning a String).
This is how you should mock your component.
jest.mock('../AccountSelectionModal', () => () => 'AccountSelectionModal');
(Notice how the function passed to mock is now returning a function)
You can also return an String but it should be in lowercase (that contains a dash), that way it would be considered as a custom element and not as a react element.
jest.mock('../AccountSelectionModal', () => 'account-selection-modal');
I try get access to method of child component.
It look like that:
1.Called method by ref name of component and then method
Form.js
this.ref.details.getDataFromComponent();
<Details
pointToShow={this.state.point}
ref="details"
/>
Details.js
getDataFromComponent() {
//do my stuff get state and connect to get data for component Details
}
All the time I have "Uncaught TypeError: Cannot read property 'ref' of null"
React 15.4.2
To access refs of a component, you need to use this.refs, not this.ref.
However, this does not seem to be the issue here, as the error clearly says that this is null when you are trying to access it. To determine why this is we need to see more of your code.
You should also look into defining refs using the ref callback attribute instead of the way you are doing it, as this syntax is no longer recommended and may be removed in future releases.
As Timo has mentioned to access an element using refs you should you should write this.refs...
According to the error you don't have access to this. Most probably you are calling this.ref.details.getDataFromComponent(); inside a method without access to this
For example you write :
callRef() {
this.ref.details.getDataFromComponent();
....
}
If so then you don't have an access to this there. You should bind your function with this.
You can either use arrow function to auto bind with this :
callRef = () => {
this.ref.details.getDataFromComponent();
....
}
Note: to use arrow function you need to use babel loader in your webpack configuration.
Or you can bind when calling the method.
For example you should call callRef() method inside jsx codes like this:
< ... onClick={this.callRef.bind(this)} />
Is there a way to evoke a method on a chart. Such as:
chart.zoomOut()
I'm struggling to find a handle for the chart object.
To render the chart i use:
<AmCharts ref={`chart_${this.props.tileid}`} {...this.chart} dataProvider={this.props.data} />
https://github.com/amcharts/amcharts3-react
I tried to inspect the element to see if I can access these methods through:
ch = this.refs[`chart_${this.props.tileid}`]
However in the 'ch' object I can not seem to find any of the methods mentioned in:
https://docs.amcharts.com/3/javascriptcharts/AmSerialChart#zoomOut
How would one reference a element to evoke a method on it?
The amchart3-react component sets the chart as a state. Thus the method can be evoked by calling:
this.refs.chartref.state.chart.zoomOut();
You will have to talk to the maintainers of amCharts3-react. The wrapper component library could have defined the component to accept as property an event-handler that is called when the wrapper's componentDidMount method has been called, so that the event-handler can grab an instance of an object that the wrapper component is a container of.
Example:
// Note, this is just a hypothetical property. It will not actually do anything
// when applied to your code.
<AmCharts onChartRendered={chart => this._amChart = chart } {...props} />
But it seems like the author of the wrapper did not define the component to accept any such property, and therefore there isn't any way for you to invoke any methods from amCharts.
Suppose I have a React component that has propTypes.
Page.propTypes = {
rawItems: React.PropTypes.string.isRequired,
};
I put the following line of code in to one of my functions
if (rawItems === React.PropTypes.string.isRequired)
Well...the 'if' returned false!! How can that be? So I played around a bit with different components and discovered that the same code used for a regular component does indeed return true. Its when I was calling this type of code for a stateless component that it returned false.
Any clues why that would be? Any other way to dynamically figure out the prop type of a prop other than doing that if stmt above?
Thank you