styled-components - test createGlobalStyle - javascript

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();
});

Related

React Fragment Not Rendering in Jest Testing

I'm testing some components and having trouble rendering the rows of a material-ui table specifically when testing with React Testing Library. I'm using react fragments to loop through an array and create the table rows of a material-ui table. I've included the code in the following code sandbox. It works as expected in this case. However, when running the tests, renders properly, but does not render it's contents.
Code Sandbox
My testing code is as follows:
// Link.react.test.js
import React from 'react';
import { cleanup, fireEvent, render, waitFor, screen } from "#testing-library/react";
import { act } from 'react-dom/test-utils';
import {InvoiceRow, InvoiceBreakdown} from '../components/billing/InvoicesBreakdown';
import SongUtils from '../components/songs/api.songs';
jest.mock('../components/songs/api.songs');
// ...
describe("SongBreakdown", function() {
test('SongBreakdown renders appropriately', async () => {
var {container} = await render(< SongBreakdown />);
screen.debug();
const tablerow = await container.querySelectorAll(".SongRow-root-1");
expect(tablerow.length).toEqual(1);
});
});
"screen.debug" Shows the resulting html after rendering. It lacks any of the react.fragments that should be printed.
Update
var {container} = await render(< SongBreakdown />);
screen.debug();
To
var {container, debug} = await render(< SongBreakdown />);
debug();

Getting child element with Enzyme

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);
});

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.

React Native jest test: TypeError: Cannot read property 'unsubscribeFromTopic' of undefined

I'm using react-native-fcm and jest to test my React Native app. I have a pretty basic test, it looks like this:
import 'react-native';
import React from 'react';
import PushController from '../app/PushController';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('works correctly', () => {
const tree = renderer.create(
<PushController />
);
});
And PushController is somewhat large, so here's the interesting parts
import React, { Component } from 'react';
import { AsyncStorage } from 'react-native';
import FCM from 'react-native-fcm';
export default class PushController extends Component {
(...)
componentDidMount() {
if (this.notificationListener) this.notificationListener.remove();
this.notificationListener = FCM.on('notification', (notif) => {
if (!notif.local_notification) {
this.notifyUser(notif.coffee);
}
});
FCM.unsubscribeFromTopic('/topics/coffee');
FCM.subscribeToTopic('/topics/coffee');
}
(...)
However, when running the test I get
__tests__/PushControllerTest.js
● works correctly
TypeError: Cannot read property 'unsubscribeFromTopic' of undefined
at Object.FCM.unsubscribeFromTopic (node_modules/react-native-fcm/index.js:86:15)
at PushController.componentDidMount (app/PushController.js:44:26)
at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:265:25
at measureLifeCyclePerf (node_modules/react-test-renderer/lib/ReactCompositeComponent.js:75:12)
at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:264:11
at CallbackQueue.notifyAll (node_modules/react-test-renderer/lib/CallbackQueue.js:76:22)
at ReactTestReconcileTransaction.ON_DOM_READY_QUEUEING.close (node_modules/react-test-renderer/lib/ReactTestReconcileTransaction.js:36:26)
at ReactTestReconcileTransaction.TransactionImpl.closeAll (node_modules/react-test-renderer/lib/Transaction.js:206:25)
at ReactTestReconcileTransaction.TransactionImpl.perform (node_modules/react-test-renderer/lib/Transaction.js:153:16)
at batchedMountComponentIntoNode (node_modules/react-test-renderer/lib/ReactTestMount.js:69:27)
I've tried including lots of stuff in the test, like jest.mock('react-native-fcm') and others, but I can't get it to work at all. I get that jest automatically mocks the library, but I don't understand why FCM is undefined. Any ideas?
I managed to solve it, finally! Simply needed to change my test to
import 'react-native';
import React from 'react';
import PushController from '../app/PushController';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
import FCM from 'react-native-fcm'; // <-- This
it('works correctly', () => {
FCM.unsubscribeFromTopic = jest.fn(); // <-- These two
FCM.subscribeToTopic = jest.fn();
const tree = renderer.create(
<PushController />
);
});
To make sure the actual calls are mocked. I did a lot of googling before this, so I'm sure this will be useful for someone.

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