testing-react-hooks-with-enzyme-and-react-testing-library

As you begin to make use of React hooks in your applications, you’ll want to be certain the code you write is nothing short of solid. There’s nothing like shipping buggy code. One way to be certain your code is bug-free is to write tests. And testing React hooks is not much different from how React applications are tested in general.

In this tutorial, we will look at how to do that by making use of a to-do application built with hooks. We’ll cover writing of tests using Ezyme and React Testing Library, both of which are able to do just that. If you’re new to Enzyme, we actually posted about it a little while back showing how it can be used with Jest in React applications. It’s not a bad idea to check that as we dig into testing React hooks.

Here’s what we want to test

A pretty standard to-do component looks something like this:

import React, { useState, useRef } from "react";
const Todo = () => {
  const [todos, setTodos] = useState([
    { id: 1, item: "Fix bugs" },
    { id: 2, item: "Take out the trash" }
  ]);
  const todoRef = useRef();
  const removeTodo = id => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
  const addTodo = data => {
    let id = todos.length   1;
    setTodos([
      ...todos,
      {
        id,
        item: data
      }
    ]);
  };
  const handleNewTodo = e => {
    e.preventDefault();
    const item = todoRef.current;
    addTodo(item.value);
    item.value = "";
  };
  return (
    

Add Todo

Lists

{!todos.length ? (
No task!
) : (
    {todos.map(todo => { return (
  • {todo.item}
  • ); })}
)}
); }; export default Todo;

Testing with Enzyme

We need to install the packages before we can start testing. Time to fire up the terminal!

npm install --save-dev enzyme enzyme-adapter-16 

Inside the src directory, create a file called setupTests.js. This is what we’ll use to configure Enzyme’s adapter.

import Enzyme from "enzyme";
import Adapter from "enzyme-adapter-react-16";
Enzyme.configure({ adapter: new Adapter() }); 

Now we can start writing our tests! We want to test four things:

  1. That the component renders
  2. That the initial to-dos get displayed when it renders
  3. That we can create a new to-do and get back three others
  4. That we can delete one of the initial to-dos and have only one to-do left

In your src directory, create a folder called __tests__ and create the file where you’ll write your Todo component’s tests in it. Let’s call that file Todo.test.js.

With that done, we can import the packages we need and create a describe block where we’ll fill in our tests.

import React from "react";
import { shallow, mount } from "enzyme";
import Todo from "../Todo";

describe("Todo", () => {
  // Tests will go here using `it` blocks
});

Test 1: The component renders

For this, we’ll make use of shallow render. Shallow rendering allows us to check if the render method of the component gets called — that’s what we want to confirm here because that’s the proof we need that the component renders.

it("renders", () => {
  shallow();
});

Test 2: Initial to-dos get displayed

Here is where we’ll make use of the mount method, which allows us to go deeper than what shallow gives us. That way, we can check the length of the to-do items.

it("displays initial to-dos", () => {
  const wrapper = mount();
  expect(wrapper.find("li")).toHaveLength(2);
});

Test 3: We can create a new to-do and get back three others

Let’s think about the process involved in creating a new to-do:

  1. The user enters a value into the input field.
  2. The user clicks the submit button.
  3. We get a total of three to-do items, where the third is the newly created one.
it("adds a new item", () => {
  const wrapper = mount();
  wrapper.find("input").instance().value = "Fix failing test";
  expect(wrapper.find("input").instance().value).toEqual("Fix failing test");
  wrapper.find('[type="submit"]').simulate("click");
  expect(wrapper.find("li")).toHaveLength(3);
  expect(
    wrapper
      .find("li div span")
      .last()
      .text()
  ).toEqual("Fix failing test");
});

We mount the component then we make use of find() and instance() methods to set the value of the input field. We assert that the value of the input field is set to “Fix failing test” before going further to simulate a click event, which should add the new item to the to-do list.

We finally assert that we have three items on the list and that the third item is equal to the one we created.

Test 4: We can delete one of the initial to-dos and have only one to-do left

it("removes an item", () => {
  const wrapper = mount();
  wrapper
    .find("li button")
    .first()
    .simulate("click");
  expect(wrapper.find("li")).toHaveLength(1);
  expect(wrapper.find("li span").map(item => item.text())).toEqual([
    "Take out the trash"
  ]);
});

In this scenario, we return the to-do with a simulated click event on the first item. It’s expected that this will call the removeTodo() method, which should delete the item that was clicked. Then we’re checking the numbers of items we have, and the value of the one that gets returned.

The source code for these four tests are here on GitHub for you to check out.

Testing With react-testing-library

We’ll write three tests for this:

  1. That the initial to-do renders
  2. That we can add a new to-do
  3. That we can delete a to-do

Let’s start by installing the packages we need:

npm install --save-dev @testing-library/jest-dom @testing-library/react

Next, we can import the packages and files:

import React from "react";
import { render, fireEvent } from "@testing-library/react";
import Todo from "../Todo";
import "@testing-library/jest-dom/extend-expect";

test("Todo", () => {
  // Tests go here
}

Test 1: The initial to-do renders

We’ll write our tests in a test block. The first test will look like this:

it("displays initial to-dos", () => {
  const { getByTestId } = render();
  const todos = getByTestId("todos");
  expect(todos.children.length).toBe(2);
});

What’s happening here? We’re making use of getTestId to return the node of the element where data-testid matches the one that was passed to the method. That’s the

    element in this case. Then, we’re checking that it has a total of two children (each child being a

  • element inside the unordered list). This will pass as the initial to-do is equal to two.

    Test 2: We can add a new to-do

    We’re also making use of getTestById here to return the node that matches the argument we’re passing in.

    it("adds a new to-do", () => {
      const { getByTestId, getByText } = render();
      const input = getByTestId("input");
      const todos = getByTestId("todos");
      input.value = "Fix failing tests";
      fireEvent.click(getByText("Add Task"));
      expect(todos.children.length).toBe(3);
    });

    We use getByTestId to return the input field and the ul element like we did before. To simulate a click event that adds a new to-do item, we’re using fireEvent.click() and passing in the getByText() method, which returns the node whose text matches the argument we passed. From there, we can then check to see the length of the to-dos by checking the length of the children array.

    Test 3: We can delete a to-do

    This will look a little like what we did a little earlier:

    it("deletes a to-do", () => {
      const { getAllByTestId, getByTestId } = render();
      const todos = getByTestId("todos");
      const deleteButton = getAllByTestId("delete-button");
      const first = deleteButton[0];
      fireEvent.click(first);
      expect(todos.children.length).toBe(1);
    });

    We’re making use of getAllByTestId to return the nodes of the delete button. Since we only want to delete one item, we fire a click event on the first item in the collection, which should delete the first to-do. This should then make the length of todos children equal to one.

    These tests are also available on GitHub.

    Linting

    There are two lint rules to abide by when working with hooks:

    Rule 1: Call hooks at the top level

    …as opposed to inside conditionals, loops or nested functions.

    // Don't do this!
    if (Math.random() > 0.5) {
      const [invalid, updateInvalid] = useState(false);
    }

    This goes against the first rule. According to the official documentation, React depends on the order in which hooks are called to associate state and the corresponding useState call. This code breaks the order as the hook will only be called if the conditions are true.

    This also applies to useEffect and other hooks. Check out the documentation for more details.

    Rule 2: Call hooks from React functional components

    Hooks are meant to be used in React functional components — not in React’s class component or a JavaScript function.

    We’ve basically covered what not to do when it comes to linting. We can avoid these missteps with an npm package that specifically enforces these rules.

    npm install eslint-plugin-react-hooks --save-dev

    Here’s what we add to the package’s configuration file to make it do its thing:

    {
      "plugins": [
        // ...
        "react-hooks"
      ],
      "rules": {
        // ...
        "react-hooks/rules-of-hooks": "error",
        "react-hooks/exhaustive-deps": "warn"
      }
    }

    If you are making use of Create React App, then you should know that the package supports the lint plugin out of the box as of v3.0.0.

    Go forth and write solid React code!

    React hooks are equally prone to error as anything else in your application and you’re gonna want to ensure that you use them well. As we just saw, there’s a couple of ways we can go about it. Whether you use Enzyme or You can either make use of enzyme or React Testing Library to write tests is totally up to you. Either way, try making use of linting as you go, and no doubt, you’ll be glad you did.

twitter-testing-tweet-scheduling-on-the-web


Marketers who aren’t using a third-party tool to compose and schedule tweets could find this quite handy.

  • More

Twitter is experimenting with a feature that lets users schedule Tweets natively on Twitter.com. The company has not confirmed how widespread the test is at this point.

Marketers who aren't using a third-party tool to compose and schedule tweets could soon have this capability right from Twitter.com
Tweet scheduling from Twitter’s TweetDeck is coming to Twitter.com.

The test was confirmed by Twitter’s standalone app TweetDeck, which enables users to manage, sort, and schedule tweets across various Twitter accounts.

Tweet scheduling on https://t.co/8FModRv1sl? Yes please! Starting today, we’re experimenting with bringing one of @TweetDeck’s handiest time-saving features into Twitter. Tell us what you think if you’re part of the experiment. pic.twitter.com/4pI9xrbPEP

— TweetDeck (@TweetDeck) November 20, 2019

Why we should care. The vast majority of Twitter users do not use TweetDeck or another third-party tool to manage their activities. Having scheduling capabilities available on Twitter.com will make it easier for more marketers, influencers and social media managers to write and schedule tweets from their desks or even on-the-go via the mobile web. If Twitter rolls out the feature to all users, brands could end up relying less on third-party social management platforms to compose and schedule content.



About The Author

Taylor Peterson is Third Door Media’s Deputy Editor, managing industry-leading coverage that informs and inspires marketers. Based in New York, Taylor brings marketing expertise grounded in creative production and agency advertising for global brands. Taylor’s editorial focus blends digital marketing and creative strategy with topics like campaign management, emerging formats, and display advertising.




facebook-testing-ads-in-groups-tab

Facebook is trying out ad placements it the Groups tab where users can view content from all the Groups they belong to. The test includes a very small number of advertisers who will have access to the new inventory within the Ads Manager, making it possible for them to extend mobile News Feed campaigns to the Groups tab.

“We’re running a small test to place ads in the Groups tab and will evaluate whether these ads are beneficial for people and businesses before deciding whether to expand it further,” said Facebook Product Manager Melisa Tokmak in an email to Marketing Land.

To take advantage of the ad placement, advertisers with access must select Facebook Feed and Group Feed placement options. Targeting capabilities for Groups tab ads remain the same as other ads. There are no additional options to target users based on their Group memberships.

Why we should care

Facebook’s test to put ads in the Groups tab is one more example of the company finding every possible opportunity it can to increase ad inventory. And with the added emphasis it has put on Groups this year — making Groups the “heart” of the Facebook experience and bringing the platform to the center of of the app — chances are good the ads being tested in the Groups tab will get exposure.

Many brands have found Facebook Groups to be advantageous in terms of organic reach as the News Feed has all but removed branded content that doesn’t have dollars attached to it. Facebook Groups offer brands the chance to build an engaged community with users who want to interact with their business on the platform. It’s not a stretch to hope those same users will be responsive to the ads inserted between the content they have opted-in to see by joining a Group.

More on the news

  • The format for Facebook Groups ads is similar to News Feed ads, with the same headline, image and copy text layout. At this time, though, only single image ads are being tested.
  • Ad campaign options include: Reach, Offsite Conversions and Link Click objectives.
  • All ads will include the “Sponsored” label and come with the same transparency and controls, such as the “Why am I seeing this ad?” information for users.


About The Author

Amy Gesenhues is a senior editor for Third Door Media, covering the latest news and updates for Marketing Land, Search Engine Land and MarTech Today. From 2009 to 2012, she was an award-winning syndicated columnist for a number of daily newspapers from New York to Texas. With more than ten years of marketing management experience, she has contributed to a variety of traditional and online publications, including MarketingProfs, SoftwareCEO, and Sales and Marketing Management Magazine. Read more of Amy’s articles.



youtube-testing-ad-buying-tool-that-lets-you-reserve-ad-placement-120-days-out

YouTube is testing a new Instant Review tool in Google Ads that allows advertisers to reserve ad space on a 120 day-rolling window via an automated process with no minimum spend. The tool is being tested globally by advertisers across multiple industries, including consumer goods, media and entertainment, food and beverage and politics.

Advertisers can use the reserve tool to book campaigns in advance with a fixed budget and forecasted reach.

Why we should care

YouTube’s Instant Reserve tool takes pages from upfront TV ad buys and programmatic guaranteed, giving advertisers the ability to reserve ad space in advance with all of the available targeting capabilities but without having to book campaigns through a sales representative. The tool will be particularly helpful for advertisers that want to plan ahead and run campaigns tied to major events — such as the upcoming U.S. presidential election. YouTube did not release an announcement when the tool was launched, but the Wall Street Journal reports political advertisers, and “hundreds” of other advertisers, were given access to it on September 3.

More on the news

  • Advertisers that use the tool can reserve ad space, but do not have to pay for the ads until they actually run on the platform, according to the Wall Street Journal.
  • An ad buyer for a political campaign told the Wall Street Journal that Google plans to let buyers reserve ad slots via the tool “for the entirety of 2020” starting November 15.
  • YouTube recently launched Video Reach campaigns for all advertisers, allowing brands to upload three different asset types in a single campaign, and brought masthead ads to its TV app.


About The Author

testing-your-email-marketing-to-improve-your-deliverability

Martech is always changing and evolving, and the same is true for one of the oldest martech applications in our toolsets — email marketing. Many organizations treat email like a static piece of marketing technology and leave email deliverability up to the email service providers, but marketing to the managed inbox needs to be an ongoing, active process. The term “managed inbox” applies to email inboxes that use filtering systems and algorithms to prioritize incoming email messages for the end-user. Ignoring email deliverability could have devastating results for your brand — like being blacklisted by major inbox providers — to which there are no quick fixes.

Marketers have more control over email optimization and deliverability than they may realize, and a few tweaks to your processes could make all the difference when it comes to reaching the inbox. Between working alongside your partners at your email service provider (ESP) and a bit of education on deliverability, your team can take control of your email marketing. “Marketers have complete control over whether they can reach the inbox,” said Tony Patti, vice president of deliverability and privacy compliance at eDataSource. “Marketers have a feeling this is permanent. If you have the knowledge of what the terms are, then the ESP knows they can communicate with you.”

The “pre-flight” checklist

Patti recommends incorporating “pre-flight” tests into your daily routine to ensure that your ESP infrastructure is up-to-date and ready to send for the day. “Always look at the infrastructure to make sure everything is correct and valid. Do a pre-flight test on everything,” Patti said. “No single item is the culprit for inbox failures, but doing a test will let you know that something is wrong. When you launch a campaign, do tests that will check for possible errors.”

Implementing a pre-flight checklist is one of the most important things marketers can do before sending an email campaign, according to Patti. This list includes double-checking content and also testing your list to ensure there are no bad email addresses being targeted.

Engagement is a must

Getting your emails delivered to the inbox is just as important as what your recipients do with those emails. We need to send content that our subscribers want to receive in order to maintain positive standings with internet service providers (ISPs).”ISPs know when users are opening, deleting, reading, removing it from spam. They keep a track record,” explained Patti.

Emails that go unopened or deleted will have a negative impact on your sender reputation and ultimately your ability to reach the managed inbox. Be clear about what your brand is offering subscribers to ensure the right people are signing up to receive your emails.

Don’t neglect your email hygiene

List management is one of the most important factors that can keep you from reaching the inbox. Implementing a step for a double opt-in from subscribers, for example, can help you keep bad email addresses off your lists. Additionally, creating processes for removing the subscribers who don’t open and click your emails after a predetermined period of time will help maintain the quality of your lists — and your brand’s sender reputation.

While there are no quick-fixes to deliverability issues, proactively testing your email campaigns for deliverability-specific metrics — including delivery rates, bounce rates and spam complaints —will help you identify gaps in your email processes and areas that need improvement. Monitoring your engagement rates (opens and clicks) will provide valuable insights into how well your content is performing with your hard-earned subscribers. Don’t shy away from removing inactive and bad email addresses for the sake of maintaining a large set of targets. “Marketers don’t get paid by the size of their list,” said Patti.

More about the Managed Inbox



About The Author

facebook-testing-two-new-ad-features:-in-app-checkout-for-facebook-ads,-new-ad-unit-for-instagram

Facebook announced Monday it is testing two new ad features: an in-app checkout experience for dynamic ads running in the Facebook News Feed and the ability to turn organic shopping posts on Instagram into an ad via Ads Manager.

“These new ads are based on the ways people currently like to discover and purchase products on Facebook and Instagram so the ad design and experience will be familiar,” said a Facebook spokesperson.

In-app checkout for Facebook News Feed ads. Facebook is testing a new native checkout feature for dynamic ads, making it possible for users to discover a product via a dynamic ad and purchase the product from the ad without ever leaving the Facebook app.

Facebook tests in-app checkout feature for dynamic News Feed ads.

This test is only being made available to a “small subset” of advertisers on Facebook during the coming weeks.

Turning organic shopping posts into Instagram ads. Facebook is also testing a new ad feature on Instagram, allowing advertisers to turn organic shopping posts into ads via the Facebook Ads Manager.

“Businesses have found success with shopping posts and will be able to reach new targeted audiences in a way that’s familiar to people,” said a Facebook spokesperson.

Facebook will be testing these ads over the next few months and said it plans to add the Instagram Checkout feature to the ads in the future (the in-app purchase feature currently available to a number of brands).

Why we should care. Facebook estimates friction in online checkout processes will cost U.S. businesses $213 billion this year. With these latest tests, Facebook is aiming to create a more efficient e-commerce process across its family of apps, building out seamless online buying experiences for businesses and advertisers already on its platforms.

Facebook has already introduced the in-app checkout feature on Instagram. By expanding in-app purchasing capabilities to its Facebook News Feed ads, the company is giving more advertisers access to a user-friendly shopping experience, all from within the Facebook ecosystem.

For Instagram advertisers, Facebook reports more than 130 million users tap on tags in Instagram shopping posts. If a business sees a shopping post doing exceptionally well in terms of engagement, this latest test will make it easier to turn that post into an ad and amplify its reach. Eventually, according to Facebook, businesses on Instagram will have the option to attach the in-app checkout feature to these ads as well, reducing the time between product discovery and purchase.



About The Author