Tuesday, May 28, 2024
 Popular · Latest · Hot · Upcoming
17
rated 0 times [  20] [ 3]  / answers: 1 / hits: 76098  / 4 Years ago, thu, february 27, 2020, 12:00:00

I'm trying to write a Jest test for a simple React component to confirm that a function has been called when I simulate a click.



However, when I use spyOn method, I keep getting TypeError: Cannot read property 'validateOnSave' of undefined. My code looks like this:



OptionsView.js



class OptionsView extends React.Component {
constructor(props) {
super(props);
this.state = {
reasonCode: null,
remarkCode: null,
otherCode: null,
codeSelectionIsInvalid: [false, false, false],
};
this.validateOnSave = this.validateOnSave.bind(this);
this.saveOptions = this.saveOptions.bind(this);

validateOnSave() {
const copy = this.state.codeSelectionIsInvalid;
copy[0] = !this.state.reasonCode;
copy[1] = !this.state.remarkCode;
copy[2] = !this.state.otherCode;
this.setState({ codeSelectionIsInvalid: copy });

if (!copy[0] && !copy[1] && !copy[2]) {
this.saveOptions();
}
}

saveOptions() {
const { saveCallback } = this.props;
if (saveCallback !== undefined) {
saveCallback({ reasonCode: this.state.reasonCode, remarkCode: this.state.remarkCode, otherCode: this.state.otherCode,
});
}
}
render() {
const cx = classNames.bind(styles);
const reasonCodes = this.props.reasonCodeset.map(reasonCode => (
<Select.Option
value={reasonCode.objectIdentifier}
key={reasonCode.objectIdentifier}
display={`${reasonCode.name}`}
/>
));
const remarkCodes = this.props.remarkCodeset.map(remarkCode => (
<Select.Option
value={remarkCode.objectIdentifier}
key={remarkCode.objectIdentifier}
display={`${remarkCode.name}`}
/>
));
const otherCodes = this.props.otherCodeset.map(otherCode => (
<Select.Option
value={otherCode.objectIdentifier}
key={otherCode.objectIdentifier}
display={`${otherCode.name}`}
/>
));
return (
<ContentContainer fill>
<Spacer marginTop=none marginBottom=large+1 marginLeft=none marginRight=none paddingTop=large+2 paddingBottom=none paddingLeft=large+2 paddingRight=large+2>
<Fieldset legend=Code sets>
<Grid>
<Grid.Row>
<Grid.Column tiny={3}>
<SelectField selectId=reasons required placeholder=Select label=Reasons: error=Required field is missing value={this.state.reasonCode} onChange={this.updateReasonCode} isInvalid={this.state.codeSelectionIsInvalid[0]}>
{reasonCodes}
</SelectField>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column tiny={3}>
<SelectField selectId=remarks required placeholder=Select label=Remarks: error=Required field is missing value={this.state.remarkCode} onChange={this.updateRemarkCode} isInvalid={this.state.codeSelectionIsInvalid[1]}>
{remarkCodes}
</SelectField>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column tiny={3}>
<SelectField selectId=other-codes required placeholder=Select label=Other Codes: error=Required field is missing value={this.state.otherCode} onChange={this.updateOtherCode} isInvalid={this.state.codeSelectionIsInvalid[2]}>
{otherCodes}
</SelectField>
</Grid.Column>
</Grid.Row>
</Grid>

</Fieldset>
</Spacer>
<ActionFooter
className={cx(['action-header-footer-color'])}
end={(
<React.Fragment>
<Spacer isInlineBlock marginRight=medium>
<Button text=Save onClick={this.validateOnSave} />
</Spacer>
</React.Fragment>
)}
/>
</ContentContainer>
);
}
}

OptionsView.propTypes = propTypes;

export default injectIntl(OptionsView);


OptionsView.test



describe('RemittanceOptions View', () => {
let defaultProps = {...defined...}
beforeAll(() => {
Object.defineProperty(window, matchMedia, {
value: jest.fn(() => {
return {
matches: true,
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
}
})
});
});

it('should validate remit codes on save', () => {
const wrapper = mountWithIntl(<OptionsView
{...defaultProps}
/>);
const instance = wrapper.instance();
const spy = jest.spyOn(instance, validateOnSave);
wrapper.setState({
reasonCode: 84,
remarkCode: 10,
otherCode: null
});
console.log(wrapper.find('Button[text=Save]').debug());
const button = wrapper.find('Button[text=Save]').at(0);
expect(button.length).toBe(1);
button.simulate('click');
expect(spy).toHaveBeenCalled();
expect(wrapper.state('codeSelectionIsInvalid')).toEqual([false,false,true]);
});
});


Ultimate goal is to test two cases when save is clicked:




  1. When state.codeSelectionIsInvalid: [false,false,true]


  2. When state.codeSelectionIsInvalid: [false,false,false]




Where am I going wrong here. Any help is appreciated!


More From » reactjs

 Answers
109

After hours of debugging, found out that the instance didn't have any methods bound. Since it is a connected component, using shallowWithIntl() and dive() resolved the error.


it('should validate remit codes on save', () => {
const wrapper = shallowWithIntl(<RemitOptionsView
{...testProps}
/>);
const button = wrapper.dive().find('Button[text="Save"]'); //Not finding the button
const instance = wrapper.dive().instance();
const spy = jest.spyOn(instance, 'validateOnSave');
instance.validateOnSave();
});

Action


[#51170] Tuesday, February 18, 2020, 4 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
jadon

Total Points: 488
Total Questions: 105
Total Answers: 105

Location: Trinidad and Tobago
Member since Thu, Dec 1, 2022
2 Years ago
;