mirror of
https://github.com/zhigang1992/create-react-app.git
synced 2026-06-10 23:39:14 +08:00
361 lines
58 KiB
HTML
361 lines
58 KiB
HTML
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>Running Tests · Create React App</title><meta name="viewport" content="width=device-width"/><meta name="generator" content="Docusaurus"/><meta name="description" content="<blockquote>
|
||
<p>Note: this feature is available with <code>react-scripts@0.3.0</code> and higher.<br></p>
|
||
</blockquote>
|
||
"/><meta name="docsearch:language" content="en"/><meta property="og:title" content="Running Tests · Create React App"/><meta property="og:type" content="website"/><meta property="og:url" content="https://create-react-app.dev/index.html"/><meta property="og:description" content="<blockquote>
|
||
<p>Note: this feature is available with <code>react-scripts@0.3.0</code> and higher.<br></p>
|
||
</blockquote>
|
||
"/><meta property="og:image" content="https://create-react-app.dev/img/logo-og.png"/><meta name="twitter:card" content="summary"/><meta name="twitter:image" content="https://create-react-app.dev/img/logo-og.png"/><link rel="shortcut icon" href="/img/favicon/favicon.ico"/><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css"/><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"/><script type="text/javascript" src="https://buttons.github.io/buttons.js"></script><script src="https://unpkg.com/vanilla-back-to-top@7.1.14/dist/vanilla-back-to-top.min.js"></script><script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
addBackToTop(
|
||
{"zIndex":100}
|
||
)
|
||
});
|
||
</script><link rel="stylesheet" href="/css/main.css"/><script src="/js/codetabs.js"></script></head><body class="sideNavVisible separateOnPageNav"><div class="fixedHeaderContainer"><div class="headerWrapper wrapper"><header><a href="/"><img class="logo" src="/img/logo.svg" alt="Create React App"/><h2 class="headerTitleWithLogo">Create React App</h2></a><div class="navigationWrapper navigationSlider"><nav class="slidingNav"><ul class="nav-site nav-site-internal"><li class="siteNavGroupActive"><a href="/docs/getting-started" target="_self">Docs</a></li><li class=""><a href="https://reactjs.org/community/support.html" target="_self">Help</a></li><li class=""><a href="https://www.github.com/facebook/create-react-app" target="_self">GitHub</a></li><li class="navSearchWrapper reactNavSearchWrapper"><input type="text" id="search_input_react" placeholder="Search" title="Search"/></li></ul></nav></div></header></div></div><div class="navPusher"><div class="docMainWrapper wrapper"><div class="container docsNavContainer" id="docsNav"><nav class="toc"><div class="toggleNav"><section class="navWrapper wrapper"><div class="navBreadcrumb wrapper"><div class="navToggle" id="navToggler"><i></i></div><h2><i>›</i><span>Testing</span></h2><div class="tocToggler" id="tocToggler"><i class="icon-toc"></i></div></div><div class="navGroups"><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Welcome<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/documentation-intro">About Docs</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Getting Started<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/getting-started">Getting Started</a></li><li class="navListItem"><a class="navItem" href="/docs/folder-structure">Folder Structure</a></li><li class="navListItem"><a class="navItem" href="/docs/available-scripts">Available Scripts</a></li><li class="navListItem"><a class="navItem" href="/docs/supported-browsers-features">Supported Browsers and Features</a></li><li class="navListItem"><a class="navItem" href="/docs/updating-to-new-releases">Updating to New Releases</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Development<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/setting-up-your-editor">Editor Setup</a></li><li class="navListItem"><a class="navItem" href="/docs/developing-components-in-isolation">Developing Components in Isolation</a></li><li class="navListItem"><a class="navItem" href="/docs/analyzing-the-bundle-size">Analyzing Bundle Size</a></li><li class="navListItem"><a class="navItem" href="/docs/using-https-in-development">HTTPS in Development</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Styles and Assets<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/adding-a-stylesheet">Adding Stylesheets</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-a-css-modules-stylesheet">Adding CSS Modules</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-a-sass-stylesheet">Adding Sass Stylesheets</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-css-reset">Adding CSS Reset</a></li><li class="navListItem"><a class="navItem" href="/docs/post-processing-css">Post-Processing CSS</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-images-fonts-and-files">Adding Images, Fonts, and Files</a></li><li class="navListItem"><a class="navItem" href="/docs/loading-graphql-files">Loading .graphql Files</a></li><li class="navListItem"><a class="navItem" href="/docs/using-the-public-folder">Using the Public Folder</a></li><li class="navListItem"><a class="navItem" href="/docs/code-splitting">Code Splitting</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Building your App<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/installing-a-dependency">Installing a Dependency</a></li><li class="navListItem"><a class="navItem" href="/docs/importing-a-component">Importing a Component</a></li><li class="navListItem"><a class="navItem" href="/docs/using-global-variables">Using Global Variables</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-bootstrap">Adding Bootstrap</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-flow">Adding Flow</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-typescript">Adding TypeScript</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-relay">Adding Relay</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-a-router">Adding a Router</a></li><li class="navListItem"><a class="navItem" href="/docs/adding-custom-environment-variables">Environment Variables</a></li><li class="navListItem"><a class="navItem" href="/docs/making-a-progressive-web-app">Making a Progressive Web App</a></li><li class="navListItem"><a class="navItem" href="/docs/production-build">Creating a Production Build</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Testing<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem navListItemActive"><a class="navItem" href="/docs/running-tests">Running Tests</a></li><li class="navListItem"><a class="navItem" href="/docs/debugging-tests">Debugging Tests</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Back-End Integration<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/proxying-api-requests-in-development">Proxying in Development</a></li><li class="navListItem"><a class="navItem" href="/docs/fetching-data-with-ajax-requests">Fetching Data</a></li><li class="navListItem"><a class="navItem" href="/docs/integrating-with-an-api-backend">Integrating with an API</a></li><li class="navListItem"><a class="navItem" href="/docs/title-and-meta-tags">Title & Meta Tags</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Deployment<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/deployment">Deployment</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Advanced Usage<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/can-i-use-decorators">Can I Use Decorators?</a></li><li class="navListItem"><a class="navItem" href="/docs/pre-rendering-into-static-html-files">Pre-Rendering Static HTML</a></li><li class="navListItem"><a class="navItem" href="/docs/advanced-configuration">Advanced Configuration</a></li><li class="navListItem"><a class="navItem" href="/docs/alternatives-to-ejecting">Alternatives to Ejecting</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Support<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/troubleshooting">Troubleshooting</a></li></ul></div></div></section></div><script>
|
||
var coll = document.getElementsByClassName('collapsible');
|
||
var checkActiveCategory = true;
|
||
for (var i = 0; i < coll.length; i++) {
|
||
var links = coll[i].nextElementSibling.getElementsByTagName('*');
|
||
if (checkActiveCategory){
|
||
for (var j = 0; j < links.length; j++) {
|
||
if (links[j].classList.contains('navListItemActive')){
|
||
coll[i].nextElementSibling.classList.toggle('hide');
|
||
coll[i].childNodes[1].classList.toggle('rotate');
|
||
checkActiveCategory = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
coll[i].addEventListener('click', function() {
|
||
var arrow = this.childNodes[1];
|
||
arrow.classList.toggle('rotate');
|
||
var content = this.nextElementSibling;
|
||
content.classList.toggle('hide');
|
||
});
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
createToggler('#navToggler', '#docsNav', 'docsSliderActive');
|
||
createToggler('#tocToggler', 'body', 'tocActive');
|
||
|
||
const headings = document.querySelector('.toc-headings');
|
||
headings && headings.addEventListener('click', function(event) {
|
||
if (event.target.tagName === 'A') {
|
||
document.body.classList.remove('tocActive');
|
||
}
|
||
}, false);
|
||
|
||
function createToggler(togglerSelector, targetSelector, className) {
|
||
var toggler = document.querySelector(togglerSelector);
|
||
var target = document.querySelector(targetSelector);
|
||
|
||
if (!toggler) {
|
||
return;
|
||
}
|
||
|
||
toggler.onclick = function(event) {
|
||
event.preventDefault();
|
||
|
||
target.classList.toggle(className);
|
||
};
|
||
}
|
||
});
|
||
</script></nav></div><div class="container mainContainer"><div class="wrapper"><div class="post"><header class="postHeader"><a class="edit-page-link button" href="https://github.com/facebook/create-react-app/edit/master/docusaurus/docs/running-tests.md" target="_blank" rel="noreferrer noopener">Edit</a><h1 class="postHeaderTitle">Running Tests</h1></header><article><div><span><blockquote>
|
||
<p>Note: this feature is available with <code>react-scripts@0.3.0</code> and higher.<br></p>
|
||
</blockquote>
|
||
<blockquote>
|
||
<p><a href="https://github.com/facebook/create-react-app/blob/master/CHANGELOG-0.x.md#migrating-from-023-to-030">Read the migration guide to learn how to enable it in older projects!</a></p>
|
||
</blockquote>
|
||
<p>Create React App uses <a href="https://jestjs.io/">Jest</a> as its test runner. To prepare for this integration, we did a <a href="https://jestjs.io/blog/2016/09/01/jest-15.html">major revamp</a> of Jest so if you heard bad things about it years ago, give it another try.</p>
|
||
<p>Jest is a Node-based runner. This means that the tests always run in a Node environment and not in a real browser. This lets us enable fast iteration speed and prevent flakiness.</p>
|
||
<p>While Jest provides browser globals such as <code>window</code> thanks to <a href="https://github.com/tmpvar/jsdom">jsdom</a>, they are only approximations of the real browser behavior. Jest is intended to be used for unit tests of your logic and your components rather than the DOM quirks.</p>
|
||
<p>We recommend that you use a separate tool for browser end-to-end tests if you need them. They are beyond the scope of Create React App.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="filename-conventions"></a><a href="#filename-conventions" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Filename Conventions</h2>
|
||
<p>Jest will look for test files with any of the following popular naming conventions:</p>
|
||
<ul>
|
||
<li>Files with <code>.js</code> suffix in <code>__tests__</code> folders.</li>
|
||
<li>Files with <code>.test.js</code> suffix.</li>
|
||
<li>Files with <code>.spec.js</code> suffix.</li>
|
||
</ul>
|
||
<p>The <code>.test.js</code> / <code>.spec.js</code> files (or the <code>__tests__</code> folders) can be located at any depth under the <code>src</code> top level folder.</p>
|
||
<p>We recommend to put the test files (or <code>__tests__</code> folders) next to the code they are testing so that relative imports appear shorter. For example, if <code>App.test.js</code> and <code>App.js</code> are in the same folder, the test just needs to <code>import App from './App'</code> instead of a long relative path. Collocation also helps find tests more quickly in larger projects.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="command-line-interface"></a><a href="#command-line-interface" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Command Line Interface</h2>
|
||
<p>When you run <code>npm test</code>, Jest will launch in watch mode<sup>*</sup>. Every time you save a file, it will re-run the tests, just like <code>npm start</code> recompiles the code.</p>
|
||
<p>The watcher includes an interactive command-line interface with the ability to run all tests, or focus on a search pattern. It is designed this way so that you can keep it open and enjoy fast re-runs. You can learn the commands from the “Watch Usage” note that the watcher prints after every run:</p>
|
||
<p><img src="https://jestjs.io/img/blog/15-watch.gif" alt="Jest watch mode"></p>
|
||
<blockquote>
|
||
<p>*Although we recommend running your tests in watch mode during development, you can disable this behavior by passing in the <code>--watchAll=false</code> flag. In most CI environments, this is handled for you (see <a href="#on-ci-servers">On CI servers</a>).</p>
|
||
</blockquote>
|
||
<h2><a class="anchor" aria-hidden="true" id="version-control-integration"></a><a href="#version-control-integration" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Version Control Integration</h2>
|
||
<p>By default, when you run <code>npm test</code>, Jest will only run the tests related to files changed since the last commit. This is an optimization designed to make your tests run fast regardless of how many tests you have. However it assumes that you don’t often commit the code that doesn’t pass the tests.</p>
|
||
<p>Jest will always explicitly mention that it only ran tests related to the files changed since the last commit. You can also press <code>a</code> in the watch mode to force Jest to run all tests.</p>
|
||
<p>Jest will always run all tests on a <a href="#continuous-integration">continuous integration</a> server or if the project is not inside a Git or Mercurial repository.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="writing-tests"></a><a href="#writing-tests" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Writing Tests</h2>
|
||
<p>To create tests, add <code>it()</code> (or <code>test()</code>) blocks with the name of the test and its code. You may optionally wrap them in <code>describe()</code> blocks for logical grouping but this is neither required nor recommended.</p>
|
||
<p>Jest provides a built-in <code>expect()</code> global function for making assertions. A basic test could look like this:</p>
|
||
<pre><code class="hljs css language-js"><span class="hljs-keyword">import</span> sum <span class="hljs-keyword">from</span> <span class="hljs-string">'./sum'</span>;
|
||
|
||
it(<span class="hljs-string">'sums numbers'</span>, () => {
|
||
expect(sum(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)).toEqual(<span class="hljs-number">3</span>);
|
||
expect(sum(<span class="hljs-number">2</span>, <span class="hljs-number">2</span>)).toEqual(<span class="hljs-number">4</span>);
|
||
});
|
||
</code></pre>
|
||
<p>All <code>expect()</code> matchers supported by Jest are <a href="https://jestjs.io/docs/en/expect.html#content">extensively documented here</a>.<br>
|
||
You can also use <a href="https://jestjs.io/docs/en/expect.html#tohavebeencalled"><code>jest.fn()</code> and <code>expect(fn).toBeCalled()</code></a> to create “spies” or mock functions.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="testing-components"></a><a href="#testing-components" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Testing Components</h2>
|
||
<p>There is a broad spectrum of component testing techniques. They range from a “smoke test” verifying that a component renders without throwing, to shallow rendering and testing some of the output, to full rendering and testing component lifecycle and state changes.</p>
|
||
<p>Different projects choose different testing tradeoffs based on how often components change, and how much logic they contain. If you haven’t decided on a testing strategy yet, we recommend that you start with creating simple smoke tests for your components:</p>
|
||
<pre><code class="hljs css language-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
|
||
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
|
||
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
|
||
|
||
it(<span class="hljs-string">'renders without crashing'</span>, () => {
|
||
<span class="hljs-keyword">const</span> div = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'div'</span>);
|
||
ReactDOM.render(<span class="xml"><span class="hljs-tag"><<span class="hljs-name">App</span> /></span>, div);
|
||
});
|
||
</span></code></pre>
|
||
<p>This test mounts a component and makes sure that it didn’t throw during rendering. Tests like this provide a lot of value with very little effort so they are great as a starting point, and this is the test you will find in <code>src/App.test.js</code>.</p>
|
||
<p>When you encounter bugs caused by changing components, you will gain a deeper insight into which parts of them are worth testing in your application. This might be a good time to introduce more specific tests asserting specific expected output or behavior.</p>
|
||
<h3><a class="anchor" aria-hidden="true" id="option-1-shallow-rendering"></a><a href="#option-1-shallow-rendering" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Option 1: Shallow Rendering</h3>
|
||
<p>If you’d like to test components in isolation from the child components they render, we recommend using <a href="https://airbnb.io/enzyme/docs/api/shallow.html"><code>shallow()</code> rendering API</a> from <a href="https://airbnb.io/enzyme/">Enzyme</a>. To install it, run:</p>
|
||
<pre><code class="hljs css language-sh">npm install --save enzyme enzyme-adapter-react-16 react-test-renderer
|
||
</code></pre>
|
||
<p>Alternatively you may use <code>yarn</code>:</p>
|
||
<pre><code class="hljs css language-sh">yarn add enzyme enzyme-adapter-react-16 react-test-renderer
|
||
</code></pre>
|
||
<p>As of Enzyme 3, you will need to install Enzyme along with an Adapter corresponding to the version of React you are using. (The examples above use the adapter for React 16.)</p>
|
||
<p>The adapter will also need to be configured in your <a href="#initializing-test-environment">global setup file</a>:</p>
|
||
<h3><a class="anchor" aria-hidden="true" id="src-setuptestsjs"></a><a href="#src-setuptestsjs" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>src/setupTests.js</code></h3>
|
||
<pre><code class="hljs css language-js"><span class="hljs-keyword">import</span> { configure } <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme'</span>;
|
||
<span class="hljs-keyword">import</span> Adapter <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme-adapter-react-16'</span>;
|
||
|
||
configure({ <span class="hljs-attr">adapter</span>: <span class="hljs-keyword">new</span> Adapter() });
|
||
</code></pre>
|
||
<blockquote>
|
||
<p>Note: Keep in mind that if you decide to "eject" before creating <code>src/setupTests.js</code>, the resulting <code>package.json</code> file won't contain any reference to it. <a href="#initializing-test-environment">Read here</a> to learn how to add this after ejecting.</p>
|
||
</blockquote>
|
||
<p>Now you can write a smoke test with it:</p>
|
||
<pre><code class="hljs css language-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
|
||
<span class="hljs-keyword">import</span> { shallow } <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme'</span>;
|
||
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
|
||
|
||
it(<span class="hljs-string">'renders without crashing'</span>, () => {
|
||
shallow(<span class="xml"><span class="hljs-tag"><<span class="hljs-name">App</span> /></span>);
|
||
});
|
||
</span></code></pre>
|
||
<p>Unlike the previous smoke test using <code>ReactDOM.render()</code>, this test only renders <code><App></code> and doesn’t go deeper. For example, even if <code><App></code> itself renders a <code><Button></code> that throws, this test will pass. Shallow rendering is great for isolated unit tests, but you may still want to create some full rendering tests to ensure the components integrate correctly. Enzyme supports <a href="https://airbnb.io/enzyme/docs/api/mount.html">full rendering with <code>mount()</code></a>, and you can also use it for testing state changes and component lifecycle.</p>
|
||
<p>You can read the <a href="https://airbnb.io/enzyme/">Enzyme documentation</a> for more testing techniques. Enzyme documentation uses Chai and Sinon for assertions but you don’t have to use them because Jest provides built-in <code>expect()</code> and <code>jest.fn()</code> for spies.</p>
|
||
<p>Here is an example from Enzyme documentation that asserts specific output, rewritten to use Jest matchers:</p>
|
||
<pre><code class="hljs css language-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
|
||
<span class="hljs-keyword">import</span> { shallow } <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme'</span>;
|
||
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
|
||
|
||
it(<span class="hljs-string">'renders welcome message'</span>, () => {
|
||
<span class="hljs-keyword">const</span> wrapper = shallow(<span class="xml"><span class="hljs-tag"><<span class="hljs-name">App</span> /></span>);
|
||
const welcome = <span class="hljs-tag"><<span class="hljs-name">h2</span>></span>Welcome to React<span class="hljs-tag"></<span class="hljs-name">h2</span>></span>;
|
||
// expect(wrapper.contains(welcome)).toBe(true);
|
||
expect(wrapper.contains(welcome)).toEqual(true);
|
||
});
|
||
</span></code></pre>
|
||
<p>All Jest matchers are <a href="https://jestjs.io/docs/en/expect.html">extensively documented here</a>.<br>
|
||
Nevertheless you can use a third-party assertion library like <a href="https://chaijs.com/">Chai</a> if you want to, as described below.</p>
|
||
<p>Additionally, you might find <a href="https://github.com/blainekasten/enzyme-matchers">jest-enzyme</a> helpful to simplify your tests with readable matchers. The above <code>contains</code> code can be written more simply with jest-enzyme.</p>
|
||
<pre><code class="hljs css language-js">expect(wrapper).toContainReact(welcome);
|
||
</code></pre>
|
||
<p>To enable this, install <code>jest-enzyme</code>:</p>
|
||
<pre><code class="hljs css language-sh">npm install --save jest-enzyme
|
||
</code></pre>
|
||
<p>Alternatively you may use <code>yarn</code>:</p>
|
||
<pre><code class="hljs css language-sh">yarn add jest-enzyme
|
||
</code></pre>
|
||
<p>Import it in <a href="#initializing-test-environment"><code>src/setupTests.js</code></a> to make its matchers available in every test:</p>
|
||
<pre><code class="hljs css language-js"><span class="hljs-keyword">import</span> <span class="hljs-string">'jest-enzyme'</span>;
|
||
</code></pre>
|
||
<h3><a class="anchor" aria-hidden="true" id="option-2-react-testing-library"></a><a href="#option-2-react-testing-library" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Option 2: React Testing Library</h3>
|
||
<p>As an alternative or companion to <code>enzyme</code>, you may consider using <code>react-testing-library</code>. <a href="https://github.com/testing-library/react-testing-library"><code>react-testing-library</code></a> is a library for testing React components in a way that resembles the way the components are used by end users. It is well suited for unit, integration, and end-to-end testing of React components and applications. It works more directly with DOM nodes, and therefore it's recommended to use with <a href="https://github.com/testing-library/jest-dom"><code>jest-dom</code></a> for improved assertions.</p>
|
||
<p>To install <code>react-testing-library</code> and <code>jest-dom</code>, you can run:</p>
|
||
<pre><code class="hljs css language-sh">npm install --save @testing-library/react @testing-library/jest-dom
|
||
</code></pre>
|
||
<p>Alternatively you may use <code>yarn</code>:</p>
|
||
<pre><code class="hljs css language-sh">yarn add @testing-library/react @testing-library/jest-dom
|
||
</code></pre>
|
||
<p>Similar to <code>enzyme</code> you can create a <code>src/setupTests.js</code> file to avoid boilerplate in your test files:</p>
|
||
<pre><code class="hljs css language-js"><span class="hljs-comment">// react-testing-library renders your components to document.body,</span>
|
||
<span class="hljs-comment">// this will ensure they're removed after each test.</span>
|
||
<span class="hljs-keyword">import</span> <span class="hljs-string">'@testing-library/react/cleanup-after-each'</span>;
|
||
<span class="hljs-comment">// this adds jest-dom's custom assertions</span>
|
||
<span class="hljs-keyword">import</span> <span class="hljs-string">'@testing-library/jest-dom/extend-expect'</span>;
|
||
</code></pre>
|
||
<p>Here's an example of using <code>react-testing-library</code> and <code>jest-dom</code> for testing that the <code><App /></code> component renders "Welcome to React".</p>
|
||
<pre><code class="hljs css language-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
|
||
<span class="hljs-keyword">import</span> { render } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
|
||
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
|
||
|
||
it(<span class="hljs-string">'renders welcome message'</span>, () => {
|
||
<span class="hljs-keyword">const</span> { getByText } = render(<span class="xml"><span class="hljs-tag"><<span class="hljs-name">App</span> /></span>);
|
||
expect(getByText('Welcome to React')).toBeInTheDocument();
|
||
});
|
||
</span></code></pre>
|
||
<p>Learn more about the utilities provided by <code>react-testing-library</code> to facilitate testing asynchronous interactions as well as selecting form elements from the <a href="https://testing-library.com/react"><code>react-testing-library</code> documentation</a> and <a href="https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples">examples</a>.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="using-third-party-assertion-libraries"></a><a href="#using-third-party-assertion-libraries" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using Third Party Assertion Libraries</h2>
|
||
<p>We recommend that you use <code>expect()</code> for assertions and <code>jest.fn()</code> for spies. If you are having issues with them please <a href="https://github.com/facebook/jest/issues/new">file those against Jest</a>, and we’ll fix them. We intend to keep making them better for React, supporting, for example, <a href="https://github.com/facebook/jest/pull/1566">pretty-printing React elements as JSX</a>.</p>
|
||
<p>However, if you are used to other libraries, such as <a href="https://chaijs.com/">Chai</a> and <a href="https://sinonjs.org/">Sinon</a>, or if you have existing code using them that you’d like to port over, you can import them normally like this:</p>
|
||
<pre><code class="hljs css language-js"><span class="hljs-keyword">import</span> sinon <span class="hljs-keyword">from</span> <span class="hljs-string">'sinon'</span>;
|
||
<span class="hljs-keyword">import</span> { expect } <span class="hljs-keyword">from</span> <span class="hljs-string">'chai'</span>;
|
||
</code></pre>
|
||
<p>and then use them in your tests like you normally do.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="initializing-test-environment"></a><a href="#initializing-test-environment" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Initializing Test Environment</h2>
|
||
<blockquote>
|
||
<p>Note: this feature is available with <code>react-scripts@0.4.0</code> and higher.</p>
|
||
</blockquote>
|
||
<p>If your app uses a browser API that you need to mock in your tests or if you just need a global setup before running your tests, add a <code>src/setupTests.js</code> to your project. It will be automatically executed before running your tests.</p>
|
||
<p>For example:</p>
|
||
<h3><a class="anchor" aria-hidden="true" id="src-setuptestsjs-1"></a><a href="#src-setuptestsjs-1" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>src/setupTests.js</code></h3>
|
||
<pre><code class="hljs css language-js"><span class="hljs-keyword">const</span> localStorageMock = {
|
||
<span class="hljs-attr">getItem</span>: jest.fn(),
|
||
<span class="hljs-attr">setItem</span>: jest.fn(),
|
||
<span class="hljs-attr">removeItem</span>: jest.fn(),
|
||
<span class="hljs-attr">clear</span>: jest.fn(),
|
||
};
|
||
global.localStorage = localStorageMock;
|
||
</code></pre>
|
||
<blockquote>
|
||
<p>Note: Keep in mind that if you decide to "eject" before creating <code>src/setupTests.js</code>, the resulting <code>package.json</code> file won't contain any reference to it, so you should manually create the property <code>setupTestFrameworkScriptFile</code> in the configuration for Jest, something like the following:</p>
|
||
</blockquote>
|
||
<blockquote>
|
||
<pre><code class="hljs css language-js"><span class="hljs-string">"jest"</span>: {
|
||
<span class="hljs-comment">// ...</span>
|
||
<span class="hljs-string">"setupTestFrameworkScriptFile"</span>: <span class="hljs-string">"<rootDir>/src/setupTests.js"</span>
|
||
}
|
||
</code></pre>
|
||
</blockquote>
|
||
<h2><a class="anchor" aria-hidden="true" id="focusing-and-excluding-tests"></a><a href="#focusing-and-excluding-tests" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Focusing and Excluding Tests</h2>
|
||
<p>You can replace <code>it()</code> with <code>xit()</code> to temporarily exclude a test from being executed.<br>
|
||
Similarly, <code>fit()</code> lets you focus on a specific test without running any other tests.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="coverage-reporting"></a><a href="#coverage-reporting" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Coverage Reporting</h2>
|
||
<p>Jest has an integrated coverage reporter that works well with ES6 and requires no configuration.<br>
|
||
Run <code>npm test -- --coverage</code> (note extra <code>--</code> in the middle) to include a coverage report like this:</p>
|
||
<p><img src="https://i.imgur.com/5bFhnTS.png" alt="coverage report"></p>
|
||
<p>Note that tests run much slower with coverage so it is recommended to run it separately from your normal workflow.</p>
|
||
<h3><a class="anchor" aria-hidden="true" id="configuration"></a><a href="#configuration" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Configuration</h3>
|
||
<p>The default Jest coverage configuration can be overridden by adding any of the following supported keys to a Jest config in your package.json.</p>
|
||
<p>Supported overrides:</p>
|
||
<ul>
|
||
<li><a href="https://jestjs.io/docs/en/configuration.html#collectcoveragefrom-array"><code>collectCoverageFrom</code></a></li>
|
||
<li><a href="https://jestjs.io/docs/en/configuration.html#coveragereporters-array-string"><code>coverageReporters</code></a></li>
|
||
<li><a href="https://jestjs.io/docs/en/configuration.html#coveragethreshold-object"><code>coverageThreshold</code></a></li>
|
||
<li><a href="https://jestjs.io/docs/en/configuration.html#snapshotserializers-array-string"><code>snapshotSerializers</code></a></li>
|
||
</ul>
|
||
<p>Example package.json:</p>
|
||
<pre><code class="hljs css language-json">{
|
||
<span class="hljs-attr">"name"</span>: <span class="hljs-string">"your-package"</span>,
|
||
<span class="hljs-attr">"jest"</span>: {
|
||
<span class="hljs-attr">"collectCoverageFrom"</span>: [
|
||
<span class="hljs-string">"src/**/*.{js,jsx,ts,tsx}"</span>,
|
||
<span class="hljs-string">"!<rootDir>/node_modules/"</span>,
|
||
<span class="hljs-string">"!<rootDir>/path/to/dir/"</span>
|
||
],
|
||
<span class="hljs-attr">"coverageThreshold"</span>: {
|
||
<span class="hljs-attr">"global"</span>: {
|
||
<span class="hljs-attr">"branches"</span>: <span class="hljs-number">90</span>,
|
||
<span class="hljs-attr">"functions"</span>: <span class="hljs-number">90</span>,
|
||
<span class="hljs-attr">"lines"</span>: <span class="hljs-number">90</span>,
|
||
<span class="hljs-attr">"statements"</span>: <span class="hljs-number">90</span>
|
||
}
|
||
},
|
||
<span class="hljs-attr">"coverageReporters"</span>: [<span class="hljs-string">"text"</span>],
|
||
<span class="hljs-attr">"snapshotSerializers"</span>: [<span class="hljs-string">"my-serializer-module"</span>]
|
||
}
|
||
}
|
||
</code></pre>
|
||
<h2><a class="anchor" aria-hidden="true" id="continuous-integration"></a><a href="#continuous-integration" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Continuous Integration</h2>
|
||
<p>By default <code>npm test</code> runs the watcher with interactive CLI. However, you can force it to run tests once and finish the process by setting an environment variable called <code>CI</code>.</p>
|
||
<p>When creating a build of your application with <code>npm run build</code> linter warnings are not checked by default. Like <code>npm test</code>, you can force the build to perform a linter warning check by setting the environment variable <code>CI</code>. If any warnings are encountered then the build fails.</p>
|
||
<p>Popular CI servers already set the environment variable <code>CI</code> by default but you can do this yourself too:</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="on-ci-servers"></a><a href="#on-ci-servers" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>On CI servers</h2>
|
||
<h3><a class="anchor" aria-hidden="true" id="travis-ci"></a><a href="#travis-ci" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Travis CI</h3>
|
||
<ol>
|
||
<li>Following the <a href="https://docs.travis-ci.com/user/getting-started/">Travis Getting started</a> guide for syncing your GitHub repository with Travis. You may need to initialize some settings manually in your <a href="https://travis-ci.org/profile">profile</a> page.</li>
|
||
<li>Add a <code>.travis.yml</code> file to your git repository.</li>
|
||
</ol>
|
||
<pre><code class="hljs css language-yaml"><span class="hljs-attr">language:</span> <span class="hljs-string">node_js</span>
|
||
<span class="hljs-attr">node_js:</span>
|
||
<span class="hljs-bullet"> -</span> <span class="hljs-number">8</span>
|
||
<span class="hljs-attr">cache:</span>
|
||
<span class="hljs-attr"> directories:</span>
|
||
<span class="hljs-bullet"> -</span> <span class="hljs-string">node_modules</span>
|
||
<span class="hljs-attr">script:</span>
|
||
<span class="hljs-bullet"> -</span> <span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">build</span>
|
||
<span class="hljs-bullet"> -</span> <span class="hljs-string">npm</span> <span class="hljs-string">test</span>
|
||
</code></pre>
|
||
<ol>
|
||
<li>Trigger your first build with a git push.</li>
|
||
<li><a href="https://docs.travis-ci.com/user/customizing-the-build/">Customize your Travis CI Build</a> if needed.</li>
|
||
</ol>
|
||
<h3><a class="anchor" aria-hidden="true" id="circleci"></a><a href="#circleci" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>CircleCI</h3>
|
||
<p>Follow <a href="https://medium.com/@knowbody/circleci-and-zeits-now-sh-c9b7eebcd3c1">this article</a> to set up CircleCI with a Create React App project.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="on-your-own-environment"></a><a href="#on-your-own-environment" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>On your own environment</h2>
|
||
<h4><a class="anchor" aria-hidden="true" id="windows-cmdexe"></a><a href="#windows-cmdexe" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Windows (cmd.exe)</h4>
|
||
<pre><code class="hljs css language-cmd"><span class="hljs-built_in">set</span> CI=true&&npm test
|
||
</code></pre>
|
||
<pre><code class="hljs css language-cmd"><span class="hljs-built_in">set</span> CI=true&&npm run build
|
||
</code></pre>
|
||
<p>(Note: the lack of whitespace is intentional.)</p>
|
||
<h4><a class="anchor" aria-hidden="true" id="windows-powershell"></a><a href="#windows-powershell" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Windows (Powershell)</h4>
|
||
<pre><code class="hljs css language-Powershell">(<span class="hljs-variable">$env:CI</span> = <span class="hljs-string">"true"</span>) -and (npm test)
|
||
</code></pre>
|
||
<pre><code class="hljs css language-Powershell">(<span class="hljs-variable">$env:CI</span> = <span class="hljs-string">"true"</span>) -and (npm run build)
|
||
</code></pre>
|
||
<h4><a class="anchor" aria-hidden="true" id="linux-macos-bash"></a><a href="#linux-macos-bash" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Linux, macOS (Bash)</h4>
|
||
<pre><code class="hljs css language-sh">CI=<span class="hljs-literal">true</span> npm <span class="hljs-built_in">test</span>
|
||
</code></pre>
|
||
<pre><code class="hljs css language-sh">CI=<span class="hljs-literal">true</span> npm run build
|
||
</code></pre>
|
||
<p>The test command will force Jest to run in CI-mode, and tests will only run once instead of launching the watcher.</p>
|
||
<p>For non-CI environments, you can simply pass the <code>--watchAll=false</code> flag to disable test-watching.</p>
|
||
<p>The build command will check for linter warnings and fail if any are found.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="disabling-jsdom"></a><a href="#disabling-jsdom" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Disabling jsdom</h2>
|
||
<p>If you know that none of your tests depend on <a href="https://github.com/tmpvar/jsdom">jsdom</a>, you can safely set <code>--env=node</code>, and your tests will run faster:</p>
|
||
<pre><code class="hljs css language-diff"> "scripts": {
|
||
"start": "react-scripts start",
|
||
"build": "react-scripts build",
|
||
<span class="hljs-deletion">- "test": "react-scripts test"</span>
|
||
<span class="hljs-addition">+ "test": "react-scripts test --env=node"</span>
|
||
</code></pre>
|
||
<p>To help you make up your mind, here is a list of APIs that <strong>need jsdom</strong>:</p>
|
||
<ul>
|
||
<li>Any browser globals like <code>window</code> and <code>document</code></li>
|
||
<li><a href="https://facebook.github.io/react/docs/top-level-api.html#reactdom.render"><code>ReactDOM.render()</code></a></li>
|
||
<li><a href="https://facebook.github.io/react/docs/test-utils.html#renderintodocument"><code>TestUtils.renderIntoDocument()</code></a> (<a href="https://github.com/facebook/react/blob/34761cf9a252964abfaab6faf74d473ad95d1f21/src/test/ReactTestUtils.js#L83-L91">a shortcut</a> for the above)</li>
|
||
<li><a href="https://airbnb.io/enzyme/docs/api/mount.html"><code>mount()</code></a> in <a href="https://airbnb.io/enzyme/index.html">Enzyme</a></li>
|
||
</ul>
|
||
<p>In contrast, <strong>jsdom is not needed</strong> for the following APIs:</p>
|
||
<ul>
|
||
<li><a href="https://facebook.github.io/react/docs/test-utils.html#shallow-rendering"><code>TestUtils.createRenderer()</code></a> (shallow rendering)</li>
|
||
<li><a href="https://airbnb.io/enzyme/docs/api/shallow.html"><code>shallow()</code></a> in <a href="https://airbnb.io/enzyme/index.html">Enzyme</a></li>
|
||
</ul>
|
||
<p>Finally, jsdom is also not needed for <a href="https://jestjs.io/blog/2016/07/27/jest-14.html">snapshot testing</a>.</p>
|
||
<h2><a class="anchor" aria-hidden="true" id="snapshot-testing"></a><a href="#snapshot-testing" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Snapshot Testing</h2>
|
||
<p>Snapshot testing is a feature of Jest that automatically generates text snapshots of your components and saves them on the disk so if the UI output changes, you get notified without manually writing any assertions on the component output. <a href="https://jestjs.io/blog/2016/07/27/jest-14.html">Read more about snapshot testing.</a></p>
|
||
<h2><a class="anchor" aria-hidden="true" id="editor-integration"></a><a href="#editor-integration" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Editor Integration</h2>
|
||
<p>If you use <a href="https://code.visualstudio.com">Visual Studio Code</a>, there is a <a href="https://github.com/orta/vscode-jest">Jest extension</a> which works with Create React App out of the box. This provides a lot of IDE-like features while using a text editor: showing the status of a test run with potential fail messages inline, starting and stopping the watcher automatically, and offering one-click snapshot updates.</p>
|
||
<p><img src="https://cloud.githubusercontent.com/assets/49038/20795349/a032308a-b7c8-11e6-9b34-7eeac781003f.png" alt="VS Code Jest Preview"></p>
|
||
</span></div></article></div><div class="docLastUpdate"><em>Last updated on 7/29/2019 by Balázs Orbán</em></div><div class="docs-prevnext"><a class="docs-prev button" href="/docs/production-build"><span class="arrow-prev">← </span><span>Creating a Production Build</span></a><a class="docs-next button" href="/docs/debugging-tests"><span>Debugging Tests</span><span class="arrow-next"> →</span></a></div></div></div><nav class="onPageNav"><ul class="toc-headings"><li><a href="#filename-conventions">Filename Conventions</a></li><li><a href="#command-line-interface">Command Line Interface</a></li><li><a href="#version-control-integration">Version Control Integration</a></li><li><a href="#writing-tests">Writing Tests</a></li><li><a href="#testing-components">Testing Components</a><ul class="toc-headings"><li><a href="#option-1-shallow-rendering">Option 1: Shallow Rendering</a></li><li><a href="#src-setuptestsjs"><code>src/setupTests.js</code></a></li><li><a href="#option-2-react-testing-library">Option 2: React Testing Library</a></li></ul></li><li><a href="#using-third-party-assertion-libraries">Using Third Party Assertion Libraries</a></li><li><a href="#initializing-test-environment">Initializing Test Environment</a><ul class="toc-headings"><li><a href="#src-setuptestsjs-1"><code>src/setupTests.js</code></a></li></ul></li><li><a href="#focusing-and-excluding-tests">Focusing and Excluding Tests</a></li><li><a href="#coverage-reporting">Coverage Reporting</a><ul class="toc-headings"><li><a href="#configuration">Configuration</a></li></ul></li><li><a href="#continuous-integration">Continuous Integration</a></li><li><a href="#on-ci-servers">On CI servers</a><ul class="toc-headings"><li><a href="#travis-ci">Travis CI</a></li><li><a href="#circleci">CircleCI</a></li></ul></li><li><a href="#on-your-own-environment">On your own environment</a></li><li><a href="#disabling-jsdom">Disabling jsdom</a></li><li><a href="#snapshot-testing">Snapshot Testing</a></li><li><a href="#editor-integration">Editor Integration</a></li></ul></nav></div><footer class="nav-footer" id="footer"><section class="sitemap"><a href="/" class="nav-home"><img src="/img/logo.svg" alt="Create React App" width="66" height="58"/></a><div><h5>Docs</h5><a href="/docs/getting-started">Get Started</a><a href="https://reactjs.org/" target="_blank" rel="noreferrer noopener">Learn React</a></div><div><h5>Community</h5><a href="https://stackoverflow.com/questions/tagged/create-react-app" target="_blank" rel="noreferrer noopener">Stack Overflow</a><a href="https://spectrum.chat/create-react-app" target="_blank" rel="noreferrer noopener">Spectrum</a><a href="https://twitter.com/reactjs" target="_blank" rel="noreferrer noopener">Twitter</a></div><div><h5>More</h5><a href="https://www.github.com/facebook/create-react-app">GitHub</a><a class="github-button" href="https://github.com/facebook/create-react-app" data-icon="octicon-star" data-count-href="/facebook/create-react-app/stargazers" data-show-count="true" data-count-aria-label="# stargazers on GitHub" aria-label="Star this project on GitHub">Star</a></div></section><a href="https://code.facebook.com/projects/" target="_blank" rel="noreferrer noopener" class="fbOpenSource"><img src="/img/oss_logo.png" alt="Facebook Open Source" width="170" height="45"/></a><section class="copyright">Copyright © 2019 Facebook Inc.</section></footer></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script><script>
|
||
document.addEventListener('keyup', function(e) {
|
||
if (e.target !== document.body) {
|
||
return;
|
||
}
|
||
// keyCode for '/' (slash)
|
||
if (e.keyCode === 191) {
|
||
const search = document.getElementById('search_input_react');
|
||
search && search.focus();
|
||
}
|
||
});
|
||
</script><script>
|
||
var search = docsearch({
|
||
|
||
apiKey: '3be60f4f8ffc24c75da84857d6323791',
|
||
indexName: 'create-react-app',
|
||
inputSelector: '#search_input_react'
|
||
});
|
||
</script></body></html> |