I'm trying to test my React application and I can successfully test reducers and component states with Simulate
on a onClick
handler, but I can't seem to test setting a component state when the change in state is based on an async request. Would love some help :) Thanks!
My test.utils file
import jsdom from 'jsdom';
import _$ from 'jquery'; // _$ instead of $ because '$', will try and reach out to browser which is not avail.
import TestUtils from 'react-addons-test-utils';
import ReactDOM from 'react-dom';
import chai, { expect } from 'chai';
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducers from '../../src/reducers/index.js';
import chaiJquery from 'chai-jquery';
// 1. Set up testing environment to run like a browser in the command line
// window (browser global env)--> global (in terminal)
global.document = jsdom.jsdom("<!doctype html><html><body></body></html>");
global.window = global.document.defaultView;
// hooking jQuery to our version of window
// don't go out to the DOM, just be responsible for the window created above
const $ = _$(global.window);
// 2. Build 'renderComponent' helper that should render a given react class
/**
* [renderComponent description]
* @param Class ComponentClass React Class or Functional Component to render
* @param Object props Props for the Component to render
* @param Object state Setting a temporary state for test purposes
* @return jQueryWrapped DOM selection
*/
function renderComponent(ComponentClass, state, props) {
// componentInstance --> rendered instance of our component
// <Provider> element is required because redux expects components to be
// rendered within a <Provider> element
const componentInstance = TestUtils.renderIntoDocument(
<Provider store={createStore(reducers, state)}>
<ComponentClass {...props}/>
</Provider>
);
// ReactDOM.findDOMNode --> gets reference to our componentInstance HTML
return $(ReactDOM.findDOMNode(componentInstance)); // produces HTML
}
// 3. Build helper for simulating events
// Adding simulate to jQuery library
$.fn.simulate = function(eventName, value) {
// "this" refers to the jQuery element form $('element') e.g. $('div');
// jQuery selectors return an array
if (value) {
this.val(value);
}
TestUtils.Simulate[eventName](this[0]);
}
// 4. Setup chai-jQuery
chaiJquery(chai, chai.util, $);
export { renderComponent, expect };
My Verify test
// Test Helpers
import {renderComponent, expect} from '../../../helpers/test_helper.js';
import TestUtils from 'react-addons-test-utils';
// Component to Test
import Verify from '../../../../src/modules/App/components/Authentication/Verify';
import authReducer from '../../../../src/reducers';
import {
USER_VERIFIED,
USER_NOT_VERIFIED,
USER_VERIFIED_UNDEFINED
} from '../../../../src/actions/types.js';
describe('Components - Authentication/Verify', () => {
let component;
it('Shows verified notice when verified', () => {
const action = { type: USER_VERIFIED };
component = renderComponent(Verify, { authReducer: { userVerified: true} });
console.log('component: ', component)
// if (authReducer({}, action).authReducer.userVerified) {
// console.log('verified: ', component)
expect(component.find('.verified-content').length).to.eql(1);
// }
});
});
My Verify component
// Other Libraries
import React, { Component } from 'react';
import { connect } from 'react-redux';
// Our Code
import { verify } from '../../../../actions/auth.js';
import { BUSINESS_TEAM_NAME } from '../../../../../utils/constants.js';
class Verify extends Component {
constructor(props) {
super(props)
this.state = { validURL: false }
}
componentWillMount() {
let params = window.location.href,
token = null;
// Check if URL contains token required by server
if (params.includes('?') && params.includes('=') && params[1].split('=')) {
if (params.indexOf('token')) {
let index;
params = params[1].split('=');
index = params.indexOf('token');
token = params[index + 1];
this.setState({ validURL: true });
} else { this.setState({ validURL: false }) }
}
// If valid token exists, verify the user
token != null ? this.props.verify(token) : '';
}
// Once user is successfully verified, render this content.
renderVerifiedContent() {
return (
<div className="container container-center-content verified-content">
<h2>Welcome to {BUSINESS_TEAM_NAME}</h2>
<p>Your account has now been verified.</p>
</div>
)
}
// Render verification error
renderLoading() {
return (
<div>Attempting to verify your account...</div>
)
}
renderUnableToVerify() {
return (
<div className="container container-center-content">
<h2>Verification Error:</h2>
<p>We are unable to verify your account right now. Please check that you clicked on the link in your email. If that doesn't work, try right-click and copy the link. Otherwise, try again later. We apologise for this inconvenience.</p>
<p>Hope you have a great day!</p>
<p>{BUSINESS_TEAM_NAME} Team</p>
</div>
)
}
render() {
return this.state.validURL
? this.props.userVerified != undefined && this.props.userVerified
? this.renderVerifiedContent()
// Only render loading if request is still in progress,
// otherwise user might still think its being verified
: this.props.userVerified == undefined ? this.renderLoading() : this.renderUnableToVerify()
: this.renderUnableToVerify()
}
}
function mapStateToProps(state) {
return {
userVerified: state.authReducer.userVerified
}
}
export default connect(mapStateToProps, { verify })(Verify);
Aucun commentaire:
Enregistrer un commentaire