How to test React template block in a component - reactjs

I am trying to test a little React component - Template block statement.
But do I can to do that? Because I can't even log that block statement from renderResult() method.
Is it possible? Only One way I see. It's just test the end result via Enzume Shallow. But I just wonder - is it possible?
Thanks for any info.
import React, { PropTypes } from "react";
export function zeta() {
return "zeta";
}
export default class AppComponent extends React.Component {
some() {
return "some";
}
renderResult() {
let res;
if (process.env.NODE_ENV === "production") {
res = ( <main><h1>App Component PROD</h1>{ this.props.children }</main> );
} else {
res = ( <main><h1>App Component DEV 11</h1>{ this.props.children }</main> );
}
return res;
}
render() {
return this.renderResult();
}
}
AppComponent.propTypes = {
children : PropTypes.object
};
My test
import jasmineEnzyme from "jasmine-enzyme";
import React from "react";
import {mount} from "enzyme";
import AppComponent, {zeta} from "../App.component";
describe("<AppComponent /> test", () => {
let wrapper;
beforeEach(() => {
jasmineEnzyme();
wrapper = mount(<AppComponent />);
});
it("App Component should contain h1", () => {
expect(wrapper.find("h1")).toBePresent();
});
it("h1 Should contain a dev text in case of dev mode", () => {
const compInst = wrapper.instance();
const res = compInst.some();
console.log(compInst.renderResult());
console.log(res);
expect(res).toMatch("some");
});
});
});

Related

NextJS: How to add screen loading for production build?

I want add screen loading in next js project. And I tried to do that with the Router component in next/router.
This is my _app.js in next.js project:
import {CookiesProvider} from 'react-cookie';
import App from 'next/app'
import React from 'react'
import {Provider} from 'react-redux'
import withRedux from 'next-redux-wrapper'
import withReduxSaga from 'next-redux-saga'
import createStore from '../src/redux/store'
import Router from "next/router";
import {Loaded, Loading} from "../src/util/Utils";
class MyApp extends App {
static async getInitialProps({Component, ctx}) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps({ctx})
}
return {pageProps}
}
render() {
Router.onRouteChangeStart = () => {
Loading()
};
Router.onRouteChangeComplete = () => {
Loaded()
};
Router.onRouteChangeError = () => {
Loaded()
};
const {Component, pageProps, store} = this.props;
return (
<CookiesProvider>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</CookiesProvider>
)
}
}
export default withRedux(createStore)(withReduxSaga(MyApp))
This is Loaded() and Loading() functions:
export const Loaded = () => {
setTimeout(() => {
let loading = 'has-loading';
document.body.classList.remove(loading);
}, 100);
};
export const Loading = () => {
let loading = 'has-loading';
document.body.classList.add(loading);
};
The code works well when the project is under development mode. But when the project is built, the loading won't disappear.
Do you know solution of this issue or are you suggesting another solution?
Using apollo client and react hooks you could do as follow.
Example:
import { useQuery } from '#apollo/react-hooks';
import gql from 'graphql-tag';
import { withApollo } from '../lib/apollo';
import UserCard from '../components/UserCard';
export const USER_INFO_QUERY = gql`
query getUser ($login: String!) {
user(login: $login) {
name
bio
avatarUrl
url
}
}
`;
const Index = () => {
const { query } = useRouter();
const { login = 'default' } = query;
const { loading, error, data } = useQuery(USER_INFO_QUERY, {
variables: { login },
});
if (loading) return 'Loading...'; // Loading component
if (error) return `Error! ${error.message}`; // Error component
const { user } = data;
return (
<UserCard
float
href={user.url}
headerImg="example.jpg"
avatarImg={user.avatarUrl}
name={user.name}
bio={user.bio}
/>
);
};
export default withApollo({ ssr: true })(Index);
More info here: https://github.com/zeit/next.js/tree/canary/examples/with-apollo
I added the following codes to a wrapper component and the problem was resolved.
componentDidMount() {
Loaded();
}
componentWillUnmount() {
Loading();
}

CytoscapeJS in create-react-app not firing console.log

I use Cytoscape.js with create-react-app. The terminal is running the app but is not outputting console.log. Especially in the handleClick method.
import React, { Component } from 'react'
import Cs from 'cytoscape'
const { cyConfig, cyStyle } = require('./config/config')
class Graph extends Component {
componentDidMount () {
cyConfig.container = document.getElementById('cy')
this.cy = Cs(cyConfig)
}
handleClick () {
this.cy.on('tap', 'node', (e) => {
const node = e.target
console.log(node.id())
})
}
render() {
return (
<div
style={cyStyle}
id='cy'
onClick={ (e) => this.handleClick(e) }
/>
)
}
}
export default Graph

Testing High-Order component with enzyme and jasmine

Testing with Jasmine and Enzyme and I've been trying to test a HOC which is connected to redux. Take for instance the following HOC:
import React, { Component } from 'react';
import { connect } from 'react-redux';
const WithAreas = (WrappedComponent) => {
class WithAreasComponent extends Component {
constructor(props) {
super(props);
}
shouldRenderWrappedComponent(userObj) {
return !!userObj.areas;
}
render() {
const { userObj } = this.props;
return shouldRenderWrappedComponent(userObj)
? <WrappedComponent {...this.props} />
: null;
}
}
function mapStateToProps(state) {
const { info } = state;
const { userObj } = info.userObj;
return { userObj };
}
return connect(mapStateToProps)(WithAreasComponent);
};
export default WithAreas;
Let's say I want to test this HOC in order to check if the wrapped component is being render according to the userObj. I thought about doing a mock component and pass it to the HOC, but this is not working.
Test.js File:
import React from 'react';
import { shallow } from 'enzyme';
import jasmineEnzyme from 'jasmine-enzyme';
import WithAreas from './';
class MockComponent extends React.Component {
render() {
return(
<div> MOCK </div>
);
}
}
function setup(extraProps) {
const props = {
info: {
userObj: {
id: 'example1'
}
},
};
Object.assign(props, extraProps);
const WithAreasInstance = WithAreas(MockComponent);
const wrapper = shallow(<WithAreasInstance {...props} />);
return {
props,
wrapper
};
}
fdescribe('<WithAreas />', () => {
beforeEach(() => {
jasmineEnzyme();
});
it('should render the Mock Component', () => {
const { wrapper } = setup();
expect(wrapper.find(MockComponent).exists()).toBe(true);
});
});
But it gives me this error:
TypeError: (0 , _.WithAreas) is not a function
at setup (webpack:///src/user/containers/WithAreas/test.js:20:47 <- src/test_index.js:9:18060087)
at UserContext.<anonymous> (webpack:///src/user/containers//WithAreas/test.js:34:24 <- src/test_index.js:9:18060822)
What am I doing wrong? Or what approach might you recommend?
Thanks for any given help.
You're not importing the HOC in test correctly. You've set it as the default export, but are using named export deconstruction.
Try this in your test file:
import WithAreas from './';
Also, don't forget to pass the store to your component in test, otherwise the connect HOC won't work as expected.
shallow(
<Provider store={store}>
<WithAreasInstance ...>
</Provider>)

jest.fn() value must be a mock function or spy received function: [Function getTemplates]

I have a function in module called handlelistOfTemplates which calls actions defined in another file. I want to test when handlelistOfTemplates is called the function in actions file is called with correct parameters.
My container component :
import React from 'react';
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import * as getData from '../../services/DataService';
class Container extends React.Component {
constructor(props){
super(props)
this.props.actions.getTemplates(1);
this.state = {
value: 1
}
}
handlelistOfTemplates = (template, index, value) => {
this.props.selectedTemplate(template);
this.setState({ value });
this.props.actions.getTemplates(template);
};
componentDidMount() {
}
render() {
return(
<ListOfTemplates listOfTemplates={this.props.listOfTemplates} value={this.state.value} onChange={this.handlelistOfTemplates}/>
);
}
}
function mapStateToProps({state}) {
return {
listOfTemplates: state.listOfTemplates
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(getData, dispatch)
};
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(Container);
And my test :
import React from 'react';
import sinon from 'sinon';
import expect from 'expect';
import { shallow } from 'enzyme';
import PropTypes from 'prop-types';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { createMockStore, createMockDispatch } from 'redux-test-utils';
import Container from './Container';
const shallowWithStore = (component, store) => {
const context = {
store,
muiTheme: getMuiTheme(),
};
const childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
store: PropTypes.object.isRequired
}
return shallow(component, { context, childContextTypes });
};
let store;
const loadComponent = (testState) => {
const props = {
actions: {
getTemplates: () => {return Promise.resolve()}
}
}
store = createMockStore(testState)
return shallowWithStore(<Container {...props}/>, store);
}
const getFakeState = () => {
return {
listOfTemplates: [],
};
}
describe('Container', () => {
let testState, component;
describe("when Appeal template is selected from select template dropdown", () => {
beforeAll(() => {
testState = getFakeState();
component = loadComponent(testState);
});
fit('should update the content in editor', (done) => {
component.dive().find('ListOfTemplates').props().onChange('Appeal', 1, 2);
component.update();
done();
expect(component.dive().state().value).toEqual(2) // error value still is at 1
expect(component.instance().props.actions.getTemplates).toHaveBeenCalled();
});
});
});
When I run the above test I get the following error.
expect(jest.fn())[.not].toHaveBeenCalled()
jest.fn() value must be a mock function or spy.
Received:
function: [Function getTemplates]
Is there something else I should be running to get this to work ?may be my mock is not correct.
even i tried doing this :
jest.spyon(component.instance().props.actions, 'getTemplates'); before expect the error remains same.
Also, when i checking the component's local state has been modified or not. I'm not getting the updated state.
when i call component.dive().find('ListOfTemplates').props().onChange('Appeal', 1, 2);
the component.dive().state().value should become 2 but it is 1 instead.
Could you please help me where i'm doing wrong?
You should pass a Mock function getTemplate to your component, otherwise jest won't be able to check whether it was called or not.
You can do that like this: (notice jest.fn() )
const props = {
actions: {
getTemplates: jest.fn(() => Promise.resolve())
}
}

How to unit test a react component that uses inheritance instead of composition using jest and enzyme?

I have a component that extends a generic component (custom react component). How do I unit-test using enzyme's mount? Here's the code:
Container.js
import React from 'react';
import request from 'API/request';
export default class Container extends React.Component {
componentDidMount() {
this.populateData();
}
componentDidUpdate() {
if (this.isDataStale()) {
return this.populateData();
}
}
populateData() {
const url = this.getUrl();
const params = this.getParams();
return request(this.props.dispatch, {
url,
params,
method: 'GET'
})
.then(response => {
this.dispatchData(response.data);
})
.catch(error => {
this.dispatchError(error);
});
}
render() {
if (this.getData() && !this.isDataStale()) {
return this.renderChildren();
} else {
return null;
}
}
getError() {}
getParams() {}
isDataStale() {
return false;
}
}
Here's the functional component:
import React from 'react';
import { connect } from 'react-redux';
import { Route, withRouter } from 'react-router-dom';
import CustomPage from 'Client/customPage';
import Container from 'Client/container';
import TestPanel from 'Client/testPanel/TestPanel';
import Greeting from 'Client/greeting';
import Button from '../Button';
export class Test extends Container {
constructor({ match }) {
super();
this.state = {
match: match,
id: match.params.id,
location: ''
};
}
isDataStale() {
return (
this.props.data.id !== this.props.match.params.id
);
}
getData() {
return this.props.data.values;
}
dispatchData(data) {
this.props.dispatch({
type: 'DATA_FOUND',
data: data,
id: this.state.id
});
}
dispatchError(error) {
this.props.dispatch({ type: 'CUSTOM_ERROR', data: error });
}
showDetails(url) {
this.props.history.push(url);
}
renderChildren() {
const match = this.state.match;
const testUrl = `/test/values/${this.state.id}`;
const verifyUrl = `${testUrl}/verify`;
return (
<div className="test-plan">
<Route path={verifyUrl} render={() => (
<Greeting show={true} />
)} />
<TestPanel
data={this.props.data}
id={this.props.match.params.id}
/>
<Route exact path={testUrl} render={() => (
<CustomPage id={this.state.id} />
)} />
<Route path={verifyUrl} render={() => (
<div className="next-button" ><Button label = {' NEXT '} onButtonClick = { this.showDetails.bind(this, loanUrl) } /> </div>
)} />
</div>
);
}
}
const mapStateToProps = state => {
return {
data: state.data
};
};
export default withRouter(connect(mapStateToProps)(Test));
How do I test this Test (functional) component using Enzyme? Am not sure how this mock works since the render method is inside the container which in turn invokes the renderChildren method in our functional component. Lot of functional components extends this container so we can't change this to composition pattern as of now.
Here's the test case (Not working)
import jsdomWindow from '../../test.setup';
import React from 'react';
import {BrowserRouter} from 'react-router-dom';
import { Test } from 'Client/containers/test';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import Enzyme, {mount} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import sinon from 'sinon';
import * as api from 'API/request';
import { populateData, isDataStale } from '../../../../src/client/app/container';
Enzyme.configure({ adapter: new Adapter() });
const sandbox = sinon.sandbox.create();
describe('<Test />',() => {
beforeEach(function() {
sandbox.stub(api, 'default').returns(Promise.resolve({data: { saySomething: 'Yay Tests!'}}));
});
afterEach(function() {
sandbox.restore();
});
const match = {
params: {
id: 100
}
};
const testState = {
data : {
test: {
id:'100',
email:'someone#something.com',
first_name:'John',
home_phone:'325-555-6564',
last_name:'Doe'
}
}
};
const wrapper = mount(
<BrowserRouter>
<Provider store={createStore(state => state, { data: testState.data })}>
<Test data={testState.data} dispatch={ sinon.spy() }
match={match} />
</Provider>
</BrowserRouter>
);
jest.mock('../../../../src/client/app/container', () => ({
populateData: jest.fn(),
isDataStale: jest.fn(),
getError: jest.fn(),
getParams: jest.fn(),
}));
it('should render', () => {
console.log(wrapper.debug());
populateData.mockReturnValueOnce({});
isDataStale.mockReturnValueOnce(false);
const greetingContainer = wrapper.find('.greeting-container').find('.quick-info').find('.quick-info-heading');
expect(greetingContainer.text()).toContain('PROPER RESPONSE');
});
// it('should render greeting component by default', () => {
// expect(wrapper.find('div.greeting-container')).toBeDefined();
// expect(wrapper.find('div.info-container')).toBeDefined();
// expect(wrapper.find('div.next-button')).toBeDefined();
// });
// it('should not render greeting and next-button components on clicking next', () => {
// console.log(`Test**** ${JSON.stringify(wrapper.find('div.plan'))}`);
// });
});
Could anyone help me to unit test this using mount method of enzyme. Don't want to use shallow here as i have to test nested components' properties.
Thank you.

Resources