Tutorials on Jest

Learn about Jest from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

The newline Guide to Practical Abstract Syntax Trees is Now Live! 🎉

Learn the practical techniques you need today to modify any large-scale codebase without the hassle of manual, one line at a time refactors.  We use real world tools such as Facebook's jscodeshift to apply these powerful concepts on actual codebases. The course goes beyond just theory to practical hands on coding , with a sample codebase we provide that you will modify as you apply the techniques you learn in the course. With  Practical Abstract Syntax Trees  you  unlock the ability to make sweeping changes in a safe and reliable way in any size codebase . We'll tackle:  It's taught by Spencer Miskoviak, who's an engineer at WealthFront, the leading automated investing services firm with over $20 billion in assets under management (AUM). Spencer is a recognized expert on ASTs and JavaScript. He presented on ASTs at React Conf in 2019, showing advanced ways to optimize a JavaScript codebase. Access The newline Guide to Practical Abstract Syntax Trees for all of the practical techniques you need to maintain any size codebase.

Thumbnail Image of Tutorial The newline Guide to Practical Abstract Syntax Trees is Now Live! 🎉

How to Write Your First Component Test in React + TypeScript App

In the previous post , we created a unit test for a function. In this post, we're going to create a unit test for a component using @testing-library/react . Since we're using Create React App the React Testing Library is already installed in our dependencies. If you don't have it, install the package using: We will create a Greetings component with the greetings text inside and a button for sending friendly waves 😊 Let's create and review a component first: This component takes a name and an onSendWaves function as props. The name will be rendered in the greetings text, and the callback function will be called whenever the button is pressed. The button can be hidden if the callback function is not provided. We need to test 3 things here: Let's start with the first one. For the first test, let's check if the greetings text is rendered correctly. Let's break the test code down a bit. In describe and it we explain the assumption we want to test as we did in the previous post . Then, we use the render method from the @testing-library/react package. This method renders the component provided in arguments and appends it to the body of the document. Once we're rendered the component we can use the screen object to get access to the render result. It provides a set of queries for us to find the required element. If you saw tests with RTL before, you might have seen this: We use getByText query to find an element that contains the given text. Notice that React Testing Library doesn't focus on the component implementation. We don't explicitly define where to look for that text, instead, we tell what to find and RTL will try to find it for us. Finally, we check that the required element is indeed in the document. We can select elements not only by the text they contain. In fact, there are quite a few ways to query elements . Let's review a couple of types of queries : Another cool (and a bit confusing at first) feature is the query type. Until now we only saw a getBy query. It searches for a single element and returns it if found and throws an error if didn't find. There are also other types of queries for different types of searches : The queryBy and queryAllBy are usually used to make sure that elements are not in the document. The findBy and findAllBy are used to search for elements that are not available at first render. It is hard to pick a query at first, that's why there is a priority guideline in the docs and the cheatsheet to help us. Now, let's test that when the onSendWaves is provided the button gets rendered: Here, we use getByRole query because we need to find a single button element. React Testing Library has the fireEvent object that can help with simulating browser events, however, it is more convenient to use the user-event library since it provides more advanced simulation of browser interactions. Let's install it with: Now let's test that when the button is pressed it fires the callback: First of all, we use jest.fn method to create a mock function . This mock will help us to test how many times and with what arguments this function has been called. On the last line, we check that the mock instance ( onSendWavesMock ) is called at least once with a given text. Another text will result in the failing test. To click the button we use the userEvent object from React Testing Library. It provides most common actions like click, input changes, and so on. In our case, we need to test the click action, so we use the click method and pass the element that should be pressed. In the next post, we will test react hooks with @testing-library/react-hook .

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More

How to Write Your First Unit Test in React + TypeScript App

Tests make sure that changes in code don't break its functionality. For testing an app, we need a test runner. Create React App provides us a test runner called jest . Let's create a new app and inspect what it contains. The src directory contains all the app code and a file called App.test.tsx . This file contains a test that makes sure that the App component renders a link: Let's break it down and write our own tests to understand what's going on. Every test is a statement that claims something. In our case, test in App.test.tsx claims that the App component should render a “Learn React” link. This kind of statements consist of 3 stages: This is true for the test in the App.test.tsx , let's check: This is considered a good practice to structure tests in this way. Tests that comply the Arrange-Act-Assert structure are clean and easy to read. Let's start with a test for good ol' functions, and then come back to testing components. Testing functions is a bit easier to grasp and it will be much easier to apply this knowledge later, when testing components. Open App.tsx and add a new function: Now, open the App.test.tsx file and start testing this divide function. First of all, we need to describe what we want to test. For descriptions, jest has a describe function , which we can use like this: We can indent describe functions to create describe specific details about current tests we write: For actually running tests jest has it and test functions . We can use either of those, they do the same. The only difference is the name semantics: we can use it to construct test sentences more naturally. For example: Finally, let's actually write our first test! In the Assert stage we used a function called expect . It is also a jest global function . It returns an object with a bunch of useful methods to use. The full list of them we can find in the docs . In our case we use .toEqual method to check if the expect argument is equal to toEqual argument, i.e. if the expected result is equal to actual result. Now, it is time to check if our test is working, open the console and run: You will see that all the tests are passing: This is great! But we have to break our test 🤯 The immediately appearing thought is: “What would we do that?”. The reason is that we need to make sure that our test is working and that it tests the right thing . Let's look at the example: So, to test our test we're going to break it and see if it breaks with the correct intent. In this case we will see an error output: If we examine the reason why the test has failed, we will see that expected value is not equal to actual. This reason is valid, so the works correctly. Now let's try to test that divide function doesn't allow to divide by 0. We know that if we try to do that it will throw. To check functions that may throw we will use .toThrow method . Notice that we pass a () => divide(1, 0) here, this way jest knows that the occurred error is expected and there is no need to stop the testing itself. Again, let's test our test: The output will be: Thus, we know that our tests are correct. Later, we will use jest for writing tests for React component.

Thumbnail Image of Tutorial How to Write Your First Unit Test in React + TypeScript App

Testing a Create React App TypeScript Project with Jest and React Testing Library

Building single-page React applications has never been easier. With a single command, Create React App (CRA) scaffolds an entire React application with development/build tools, such as Babel and Jest, automatically configured and integrated into the project. Getting started requires no additional configuration. Plus, it eliminates the need to maintain an entire build process, which can require lots of work and is very prone to error. However, the default template of Create React App does not include support for TypeScript, which has gained much traction in recent years. Below, I'm going to show you: To generate a new CRA project with TypeScript, provide the --template option to create-react-app and specify typescript as the template. Once the process is complete, view the project in an IDE (such as VSCode). Take note of the few differences between this template and the default template. Of course, TypeScript can be added to an existing CRA project by reproducing the above modifications. Replicating these steps on each new CRA project would be quite tedious and would waste valuable time that could be put towards designing/building your application. The CRA typescript template instantly did all this work for us. CRA templates simply offer conveniences that cannot be overlooked. Run the CRA application. You should see the following in your browser at localhost:3000 . Inside of src/App.test.tsx , there is a single unit test. ( src/App.test.tsx ) Run tests by executing the test NPM script: The test checks whether the "Learn React" link is rendered to the page. The React Testing Library ( @testing-library/react ) provides APIs for testing React components: Now, let's write several additional tests for the CRA TypeScript template project. To test if the React logo is rendered, use the getByAltText method, a semantic query method used for finding elements that support the alt attribute (such as <img /> ). This test should automatically pass. To test if the prompt to the user ("Edit src/App.tsx and save to reload") is rendered, use the getByText method. When you run the tests, you will notice that this test fails. This test fails because the query method encounters elements with parts of their text content wrapped in other elements such as <strong /> , <em /> , etc. Example : As the error message mentions, this issue can be resolved by passing a custom function as the text matcher argument to the getByText method. The function is executed on each node that's rendered to the page. When the function evaluates to true for a node, then that node will be returned as a matching node. On the contrary, when the function evaluates to false for a node, then that node will be ignored. This function accepts two arguments: Running the tests once more, all the tests pass. Experiment! Try out other queries and methods provided by the React Testing Library. The code for this post can found here . If you want to learn more about testing TypeScript + React with Jest and React Testing Library, then check out Fullstack React with TypeScript :

Thumbnail Image of Tutorial Testing a Create React App TypeScript Project with Jest and React Testing Library

Jest VSCode Plugin

When writing tests for your application, it can be tedious and distracting to switch between the terminal and IDE to execute tests and verify that all tests are passing. What if there was a more streamlined approach that simply displayed the results of tests directly within the IDE, with each result (passing or failing) adjacent to its corresponding test? If you are writing tests using the Jest framework, and your IDE of choice is VSCode, then there is a plugin in the VSCode marketplace that automatically runs tests and shows individual test results inline. Getting this immediate feedback within the editor improves productivity and reduces context switching. Below, I'm going to show you: Click the "Extensions" icon in the Activity Bar on the left-side of the VSCode window and type "jest" into the search bar at the top of the Extensions view. Select the result with the publisher "Orta" (the first result with the most downloads). Install the plugin by clicking on the green "Install" button. When you open a project in VSCode with a Jest installation (detects Jest in node_modules ), this plugin will automatically start Jest. To demonstrate the capabilities of this plugin, we will explore how it runs for an existing project with Jest installed. Download this project from GitHub: Open the project in VSCode, navigate to the __tests__/index.test.ts file and open it. Take note of the checkmarks, which each indicate a passing test, preceding each it . If it doesn't show up automatically, then manually start the runner: To enable debugging for Jest tests, create a .vscode directory in the root of the project, and inside of this directory, add a launch.json configuration file that contains the following: ( .vscode/launch.json ) Here's what each configuration option does: In short, this configuration automatically launches and attaches the VSCode Node.js debugger to a process running the tests. Let's revisit __tests__/index.test.ts and make a small adjustment to one of the tests. For the first test, store the hex and RGB literals in an object, and reference their values from this object. ( __tests__/index.test.ts ) Place a breakpoint on the line with the assertion: Launch Command Palette ( CMD + SHIFT + p on Mac or CTRL + SHIFT + p on Windows). Select the option "Debug: Select and Start Debugging," followed by "Debug rgb-hex Tests." On the left, a debug pane with runtime variables, call stack and breakpoint sections will be shown. Notice how the values of the local variables (in this case, white ) can be observed. On the top, there will be control buttons that can be used to step through, restart or stop the execution of the tests. Since there are no more breakpoints, press the red square button in the control buttons group to stop the execution of the tests. Experiment! Add more tests and breakpoints. Explore VSCode's debugger's other features . If you want to learn more about testing TypeScript + React applications with Jest, then check out Fullstack React with TypeScript :

Thumbnail Image of Tutorial Jest VSCode Plugin

Testing TypeScript Code with Jest

Jest is an open-source, JavaScript testing framework maintained by Facebook. With an exceptionally large assertion library and a simple, well-documented API , writing tests for JavaScript code with Jest is easy and requires no additional configuration. For TypeScript code (and JavaScript code that needs to be transcompiled with Babel), you will need to install a few extra NPM packages and provide a small Babel configuration. This process is not difficult and takes little time to complete. By setting up TypeScript and Jest in the early stages of your project, this upfront investment will pay exponential dividends in the latter stages of your project. Below, I'm going to show you: Pairing TypeScript and Jest creates layers of code quality assurance for any project. With TypeScript, static type-checking can immediately catch many common mistakes such as invalid arguments being passed to a function, etc. Adding type annotations not only enforces type checking, but also serves as a form of documentation. Editors with intelligent code completion are able to instantly notify the developer of potential bugs in their code. VSCode Intellisense (JavaScript) : VSCode Intellisense (TypeScript) : With Jest, a robust test suite can be written with little boilerplate code. Plus, developers are able to confidently refactor or add features to an application without having to worry about introducing new unexpected bugs or regressions to other parts of the application. The combination of TypeScript and Jest ultimately leads to long-term maintainability. To demonstrate how quick it is integrate Jest into a TypeScript project, we will add Jest to a small Node.js library built with TypeScript. Download this project from GitHub: Note : The "master" branch hosts the library with Jest. If you find yourself lost during the walkthrough, then feel free to refer to the code in the "master" branch. Install Jest as a dev. dependency. Because Jest supports TypeScript via Babel, install @babel/plugin-transform-typescript , a plugin that adds support for the TypeScript syntax, as a dev. dependency. To use import statements in Jest test files (and support the latest, commonly-used JavaScript features), install @babel/preset-env as a dev. dependency. A single preset conveniently contains an array of Babel plugins. This eliminates the need to manually install individual Babel plugins for standard JavaScript features that you would expect out-of-the-box support for such as @babel/plugin-transform-arrow-functions for arrow functions and @babel/plugin-transform-spread for the spread operator. Add a babel.config.js file to the root of the project to configure Babel with these presets. Set the target environment of @babel/preset-env to the current version of Node that you are running, which allows Babel to only transpile features that are not natively supported by the specified environment. ( babel.config.js ) This library provides two simple methods for converting color values, rgbToHex and hexToRgb : Let's add several unit tests for each method. In the root of the project, create a __tests__ directory. Inside of that directory, create a new file named index.test.ts . Inside of index.test.ts , define two top-level describe blocks to encapsulate all the unit tests. Each block will group together unit tests related to one of the methods. ( __tests__/index.test.js ) Next, at the top of the index.test.ts file, import the methods rgbToHex and hexToRgb . ( __tests__/index.test.js ) Inside the body of the first describe block (housing rgbToHex tests), let's write some simple tests. Each it block represents a single test (also called spec), and inside of each test is an assertion. ( __tests__/index.test.js ) To test the code, add the following NPM script to package.json and execute it. ( package.json ) All the tests should pass with flying colors! Now let's test the remaining method hexToRgb . Inside the body of the second describe block (housing hexToRgb tests), let's write some simple tests. ( __tests__/index.test.js ) When you run the tests, all the tests should pass with flying colors! If you happen to forget what kind of arguments need to be passed to a method, or need to be reminded of what the method does via a documentation comment (JSDoc/TSDoc), then hover over the method name and Intellisense will display a tooltip with the full function signature (with type annotations) and along with the comment. Experiment! Visit the Jest documentation and add more tests using some of the other matcher functions. If you want to learn more about testing TypeScript with Jest, then check out Fullstack React with TypeScript :

Thumbnail Image of Tutorial Testing TypeScript Code with Jest

Testing Custom React Hooks with Jest

Hooks in React are a new, popular, and extensible way to organize side-effects and statefulness in React components. By composing the base hooks provided by React, developers can build their own custom hooks for use by others. Redux, ApolloClient, and Callstack have distributed custom hooks to access your app's store, client, and themes using the useContext hook. You can also compose useEffect and useState to wrap API requests or wrap the concept of time. It's powerful. It's simple. These two statements are not a coincidence, either: the power is the simplicity. The same goes for testing custom React hooks. By the end of this write-up, you'll think testing hooks as simple, too. We'll learn about React hooks, React in general, some basics of unit testing, and the bigger picture when it comes to automated testing. Don't panic, it's all right here in GitHub . Give the repo a star before cloning. React hooks are not quite normal functions. They need to run in a React render context, otherwise, they will give you an annoying error. Other literature on this topic suggests building a React component in the test and hacking that to test your hook's functionality using component testing tools like Enzyme. I found this approach to be brittle (who wants to maintain an unused component for every hook change?) and unnecessary. Try using the react-hooks-testing-library . It makes testing React hook behavior, parameters, and return values a breeze. Much easier than dealing with Enzyme, for example. Key concepts are the renderHook and act utilities. The first is where to specify your React Hook, context, and parameters. For instance, here is how to set up and test a React hook's parameters and return value. The act utility is for triggering side-effects for your hook to respond, like events or changing props. It is the same as the act provided by React . We'll see it in action later when we learn (spoiler alert) time control. Mocking is like the beginning of an Indiana Jones movie. It's like filling a bag with sand so when we swap the sandbag with the treasure, the detector doesn't trigger the trap. The detector has to not see the difference between the mock and the real thing. For example, you can mock axios so your hook does all the steps to send an HTTP request without actually sending a request. Plus, because you control the mock of axios , you can decide when the promise resolves or rejects. In React, dependencies can be your package.json dependencies or the exports of other source modules through import/requires, provided through context, or defined elsewhere in the file. If your hook depends on it in order to work, then it's a depend ency. When it comes to testing anything, from a web application to - yes - a React hook, there are different levels at which we can test. The core question of automated testing is this: how much should we mock? If we mock too many dependencies, we lose confidence that the system works as a whole. However, if we mock too few, the sheer number of moving parts cause our tests to be slower, less reliable, and harder to debug/pinpoint failures. If you want to learn more about managing software quality and automated testing, check out these 2014 slides from Google engineering. The prevailing wisdom is to have more small tests with mocks and a few large and valuable end-to-end tests. This is often visualized using a pyramid, called the "testing pyramid". In essence, most of your tests should mock a lot (unit tests), then some tests should mock less and ensure lower-level units are wired up together properly (integration tests), and then fewer tests mock even less and ensure the mid-size units interact properly (also integration tests). At the top of the pyramid, tests should have no mocks yet be very few in number (end-to-end tests). To use another analogy: if you were testing a car, you would test if the sparkplug works, then make sure the assembled piston works after testing its parts, then make sure the engine works after testing its parts, then make sure the whole car starts and survives a lap around the track after testing the gearbox, chassis, brakes, etc. Your hooks rely on dependencies to get almost anything done. Maybe your hook reads state from a Redux store, or perhaps your hook triggers HTTP requests or GraphQL queries. When unit testing React hooks, you want to avoid depending on anything outside of your UI code, like backend or browser APIs. That way, your tests failing means the problem is with the UI and not somewhere else. Test frameworks give the ability to create mock functions. I find the Sinon.js documentation for stubs (same idea, different terminology) does a nice job teaching this concept and showing examples. In Jest, the key is jest.fn() or jest.spyOn() for mocking methods. For our purposes, mocking allows us to fashion a fake function or object without calling the true implementation, avoiding unwanted side-effects. For example, if I have a class controlling an alert noise in my application, I can call jest.spyOn(NoiseService, 'playLoudHorn') to have that function call, when tested, not try to make a real noise. If the method is supposed to return a boolean to indicate success/failure, you can do .mockReturnValue(true) on the end of a mock to have the mocked function return true for this test. The hard part about stubbing/mocking is getting access to the dependency so we can spyOn it or so we can replace it entirely with a mock. The rest of this article is about several ways to inject our mocks into a React hook. In pure functions, all dependencies are passed as arguments to the function. The benefit of this approach is it makes providing (injecting) dependencies during tests straight-forward. Outside of testing, if the dependencies are given default values, the original functionality can be preserved. In this useTime() hook ( read the Medium article for implementation details ), a _getTime parameter is exposed to allow specifying a different function to get the current time. ( I used Luxon for handling DateTimes , I like it more than momentjs) Suppose I want to control what time my useTime() hook thinks it currently is. Instead of mocking the Date object or spying on DateTime.local , I can simply pass in a mock function as _getTime . Here's a test where we do exactly that: (For this test, the actual return value of _getTime is not critical, so I used a string) Of course, by specifying a default function, I can avoid specifying the getTime option when consuming the hook in my components. Here's a sample usage of the useTime hook, without any _getTime specified. An alternative way to control/spy/mock an import is to use the Jest module mocking tools (or tools like proxyquire ) to inject mocks through the module system. Just specify the exact string used for require-ing the dependency, then provide your own mock before importing the unit under test. While this example works, I find with larger test files it can be prone to mutation by tests and can, as a result of mutation behavior, become more complicated. Tests should be easy. Dependencies in React can be provided through the React Context API. This is how components connected to Redux store are able to access state, for example. Let's look at a trivial hook which accesses a context to build a URL string based on a configuration object. We're going to test useResumeURL() . Here's a sample usage: In our test, we can rely on default context, or we can specify a new context using the wrapper option from @testing-library/react-hooks to loop in the context's Provider to inject a mock context value. Let's do both: Made a quick testing factory to build wrappers, so future tests would not be tied to a specific set of values. Keeps tests independent, which is a best practice. Some dependencies can be controlled in unconventional ways. setTimeout and setInterval (generally, the concept of time) can be controlled using Jest ( and Sinon.js, used in this example ). Through experimentation, I found the passage of time has to occur inside act callbacks for the hook to register the effects properly. Another common unconventional dependency mock wraps the XMLHttpRequest (XHR) object so you can block and assert on outgoing network requests, plus control the responses and test the resulting behavior (very nice for testing uncommon API failure scenarios).

Thumbnail Image of Tutorial Testing Custom React Hooks with Jest