Getting child element with Enzyme - javascript

I want to run a test, such that for my shallow enzyme wrapper, I can determine if that wrapper contains the correct child element. For example, given the below code and my defined wrapper, I want to run some kind of function or something (someFn()) so that I return the child elements within my wrapper (in this case, <p>this is some text</p>). Is there a way to do this? Currently wrapper.getElement() will return me <div test-attr="div"><p>this is some text</p></div>, which is not exactly what I'm looking for. Thanks!
sampleComponent.js:
import React from 'react';
const SampleComponent = () => (
<div test-attr="div">
<p>this is some text</p>
</div>
);
export default SampleComponent;
sampleComponent.test.js:
import React from 'react';
import { shallow } from 'enzyme';
import SampleComponent from './sampleComponent';
test('renders icon without errors', () => {
const wrapper = shallow(<SampleComponent />);
const div = wrapper.find('[test-attr="div"]');
const expectedChildElement = <p>this is some text</p>;
expect(div.someFn()).toEqual(expectedChildElement);
});

You can use children() method along with html().
Here is the working test case:
import React from 'react';
import { shallow } from 'enzyme';
import SampleComponent from './sampleComponent';
test('renders icon without errors', () => {
const wrapper = shallow(<SampleComponent />);
const div = wrapper.find('[test-attr="div"]');
const expectedChildElement = "<p>this is some text</p>";
//console.log(div.children().debug());
expect(div.children().html()).toEqual(expectedChildElement);
});

Related

Force React component that have not mounted to DOM render?

I have a class that's a component of React. How can I force that class render and return to me a DOM element?
For example:
class MyComponent extends React.Component{...}
const myVirtualDOMComponentButNotMountToAnywhere = <MyComponent {...someprops} />
// is there any function that
const myDOMElement = MyComponent.createDOMElement();
// or
const myDOMElement = myVirtualDOMComponentButNotMountToAnywhere.renderAsDOMElement();
// return a result that similar to
document.createElement(...);
I want to get that DOM element to perform custom mount (or what ever I want to) to that DOM element as the result from my function I expect that similar to the result of document.createElement().
For another example as a real usecase:
import { Link } from 'react-router-dom';
const myLink = <Link to='/...' />
const myDOMLink = myLink.renderAsDOMElement();
document.getElementById('someId').appendChild(myDOMLink);
I may was too overthinking. It was provided as an API of react-dom: render
import ReactDOM from 'react-dom';
ReactDOM.render(<MyComponent />, document.getElementById('someId'))

styled-components - test createGlobalStyle

How is it possible to make snapshot tests with styled-components createGlobalStyle?
Tests are running with jest v22.4.4, and styled-components v4.1.2, react v16.7 and jest-styled-components v5.0.1 and react-test-renderer v16.6.3
The output of the snapshot is without the css. but I need a way to test if the css had changes...
E.g.
const BaseCSS = createGlobalStyle`
a { color: red };
`;
And a test
import React from 'react';
import renderer from 'react-test-renderer';
import 'jest-styled-components';
import { BaseCSS } from '../src';
test('test if e', () => {
const tree = renderer.create(<div><BaseCSS /> Test</div>).toJSON();
expect(tree).toMatchSnapshot();
});
edit:
The output of the snapshot looks like: (there is no css in the snapshot)
exports[`test if e 1`] = `
<div>
Test
</div>
`;
I found an answer here and it works!
The global style component will "live" in the <head> tag, not inside the <body> so "you should have aimed for the head".
Here is my working example:
import "jest-styled-components";
import React from "react";
import renderer from "react-test-renderer";
import GlobalStyle from "../../src/styles/GlobalStyle.js";
it("should have global style", () => {
renderer.create(<GlobalStyle />);
expect(document.head).toMatchSnapshot();
});

Is it possible to get the full page html when using React/Enzyme/Jest with Nextjs?

I've got a React component that looks like:
import React from 'react';
import Head from 'next/head';
export default class extends React.Component {
static defaultProps = {
language: 'en',
country: 'us'
};
...
render () {
const language = this.props.language || 'en';
const country = this.props.country || 'us';
return (
<div className="edf-header">
<div className="desktop-header"></div>
<div className="mobile-header"></div>
<Head>
<script dangerouslySetInnerHTML={{__html: `
var secure = "//local-www.hjjkashdkjfh.com";
var perfConfig = {
LOCALE: '${language}_${country}',
I want to confirm, via a test, that the perfConfig is built correctly. I'm testing it with:
import React from 'react';
import Enzyme from 'enzyme';
import Foo from '../../components/Foo';
import Adapter from 'enzyme-adapter-react-16';
import enzymify from 'expect-enzyme';
import Head from 'next/head';
const {mount, shallow, render} = Enzyme;
Enzyme.configure({adapter: new Adapter()});
expect.extend(enzymify());
...
it('renders correct nsgConfig', () => {
const foo = render(<Foo country='ca' language='fr'/>);
console.dir(foo.html());
expect(foo.find('Head')).toExist();
expect(foo.html().indexOf("LOCALE: 'fr_ca'")).toBeGreaterThan(0);
});
The problem is that the html doesn't contain a head tag. The html has the divs but that's it.
How do I get Next/Enzyme to work together here to render the full page? Tried shallow and mount with no luck.
The Head component adds its children to the actual once the page is mounted. You would have to render the full page starting from the _document component. In my tests mount seems to be using a "div" tag where it inserts the component and complains if you actually mount a "head" component so I'm not sure this is even possible.

Testing react component's number of children

I am writing a test in React for the first time, and I am wondering is there a way to test the number of children components of a children component inside the parent component, so to make it clear, this is how to component looks like, I have cut it down to the parts that are relevant to this question:
<Modal>
<RadioGroupField direction="vertical" name={`${fieldId}.resultat`} bredde="M">
<RadioOption label={{ id: 'UttakInfoPanel.SykdomSkadenDokumentertAngiAvklartPeriode' }} value />
<RadioOption label={{ id: 'UttakInfoPanel.SykdomSkadenIkkeDokumentert' }} value={false} />
</RadioGroupField>
</Modal>
So, when I am writing a test for the Modal component I would like to check if there is a correct number of children components of the RadioGroupField component:
import React from 'react';
import { expect } from 'chai';
import { shallowWithIntl } from 'testHelpers/intl-enzyme-test-helper';
import { Modal} from './Modal';
const periode = {
fom: '2018-01-01',
tom: '2018-03-01',
};
it('should show modal component', () => {
const wrapper = shallowWithIntl(<Modal
fieldId="periode[0]"
resultat={undefined}
periode={periode}
/>);
const radioGroupField = wrapper.find('RadioGroupField');
expect(radioGroupField).to.have.length(1);
});
How can I write that test?
Update
I have tried with using name and not string for the component and dive method, but all of a sudden I get an error:
ReferenceError: RadioGroupField is not defined
This is my test:
it('skal vise sykdom og skade periode', () => {
const wrapper = shallowWithIntl(<Modal
fieldId="periode[0]"
resultat={undefined}
periode={periode}
/>);
const textAreaField = wrapper.find('TextAreaField');
const undertekst = wrapper.find('Undertekst');
const radioGroupField = wrapper.find('RadioGroupField');
const fieldArray = wrapper.find('FieldArray');
const hovedknapp = wrapper.find('Hovedknapp');
const knapp = wrapper.find('Knapp');
const radioGroupFieldComponent = wrapper.find(RadioGroupField).dive();
expect(radioGroupFieldComponent.children()).to.have.length(2);
expect(textAreaField).to.have.length(1);
expect(undertekst).to.have.length(1);
expect(radioGroupField).to.have.length(1);
expect(fieldArray).to.have.length(1);
expect(hovedknapp).to.have.length(1);
expect(knapp).to.have.length(1);
});
In order to refer to components, use their name not a String as documented:
wrapper.find(Foo) // Foo component, not 'Foo'
I would like to check if there is a correct number of children components of the RadioGroupField component:
Use children() as documented in the enzyme API
const radioGroupField = wrapper.find(RadioGroupField).dive()
expect(radioGroupField.children()).to.have.length(2)
References:
enzyme find() api
enzyme children() api
EDIT:
add dive() as this may be needed to render components (non-DOM nodes)
Update
I have tried with using name and not string for the component and dive
method, but all of a sudden I get an error:
ReferenceError: RadioGroupField is not defined
Any components used in your tests need to be imported.
Here's an example:
Foo.js:
import React from 'react'
export const Bar = (props) => {
return (
<div>
{props.children}
</div>
)
}
export const Baz = () => (
<div>Foo</div>
)
export const Foo = () => (
<Bar>
<Baz />
<Baz />
</Bar>
)
export default Foo
Foo.test.js
import React from 'react'
import { shallow } from 'enzyme'
import Foo, { Bar, Baz } from './Foo'
it('Foos', () => {
let wrapper = shallow(<Foo />)
expect(wrapper.find(Bar)).toHaveLength(1) // jest syntax
})
This also works:
const radioOption = wrapper.find(RadioGroupField).dive().find(RadioOption);

Refs are null in Jest snapshot tests with react-test-renderer

Currently I am manually initializing Quill editor on componentDidMount and jest tests fail for me. Looks like ref value that I am getting is null in jsdom. There is and issue here: https://github.com/facebook/react/issues/7371 but looks like refs should work. Any ideas what I should check?
Component:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
componentDidMount() {
console.log(this._p)
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro" ref={(c) => { this._p = c }}>
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
Test:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import renderer from 'react-test-renderer'
it('snapshot testing', () => {
const tree = renderer.create(
<App />
).toJSON()
expect(tree).toMatchSnapshot()
})
As a result, console.log outputs null. But I would expect P tag
Since test renderer is not coupled to React DOM, it doesn't know anything about what refs are supposed to look like. React 15.4.0 adds the ability to mock refs for test renderer but you should provide those mocks yourself. React 15.4.0 release notes include an example of doing so.
import React from 'react';
import App from './App';
import renderer from 'react-test-renderer';
function createNodeMock(element) {
if (element.type === 'p') {
// This is your fake DOM node for <p>.
// Feel free to add any stub methods, e.g. focus() or any
// other methods necessary to prevent crashes in your components.
return {};
}
// You can return any object from this method for any type of DOM component.
// React will use it as a ref instead of a DOM node when snapshot testing.
return null;
}
it('renders correctly', () => {
const options = {createNodeMock};
// Don't forget to pass the options object!
const tree = renderer.create(<App />, options);
expect(tree).toMatchSnapshot();
});
Note that it only works with React 15.4.0 and higher.
I used Enzyme-based test from this repo to solve this issue like that:
import { shallow } from 'enzyme'
import toJson from 'enzyme-to-json'
describe('< SomeComponent />', () => {
it('renders', () => {
const wrapper = shallow(<SomeComponent />);
expect(toJson(wrapper)).toMatchSnapshot();
});
});

Categories

Resources