0

I need to access and test a method of a child component in react using Jest. I am not using Enzyme, so this is not a duplicate of this question or this question. I would like to use React Testing Library instead of Enzyme.

Earlier I was happily accessing the methods I needed to test like this:

import React from "react";
import { render, unmountComponentAtNode } from "react-dom";
import App from "./App";

let container: any = null;
beforeEach(() => {
    // setup a DOM element as a render target
    container = document.createElement("div");
    document.body.appendChild(container);
});

afterEach(() => {
    // cleanup on exiting
    unmountComponentAtNode(container);
    container.remove();
    container = null;
});

test("methodToTest should do what I want it to", () => {
    const { methodToTest } = render(<App />, container);
    methodToTest("some input");
    const output = document.querySelector(".outputFromMethod");
    expect(output.innerHTML).toBe("You gave me some input");
});

But now I need to wrap my <App /> component in withRouter() from react-router-dom, so I have to do something like this: (Based on the recipe suggested by React Testing Library)

import React from "react";
import { BrowserRouter as Router } from "react-router-dom";
import { render, unmountComponentAtNode } from "react-dom";
import App from "./App";

let container: any = null;
beforeEach(() => {
    // setup a DOM element as a render target
    container = document.createElement("div");
    document.body.appendChild(container);
});

afterEach(() => {
    // cleanup on exiting
    unmountComponentAtNode(container);
    container.remove();
    container = null;
});

test("methodToTest should do what I want it to", () => {
    // THIS DOESN'T WORK NOW FOR GETTING methodToTest
    const { methodToTest } = render(<Router><App /></Router>, container);
    const output = document.querySelector(".outputFromMethod");
    expect(output.innerHTML).toBe("You gave me some input");
});

I understand that it's not ideal to try to test methods on a child component. But I need to do this because I have to have this component render inside of a <Router>. Is there any way to access the <App /> components methods without using Enzyme, or using React Testing Library if necessary?

Adam D
  • 1,370
  • 1
  • 13
  • 29
  • Have you already tried the `wrapper` approach? – Jacob Sep 24 '19 at 23:36
  • @Jacob yes but it appears that methods from the component are not available when using the `render` from `@testing-library/react` (which has the `wrapper` option). I am asking about this here: https://github.com/testing-library/react-testing-library/issues/492 – Adam D Sep 25 '19 at 02:32

1 Answers1

2

You can't do that with Testing Library, that's against the principles. You're also using a strange style for testing. Have you tried to do this:

import React from "react";
import { BrowserRouter as Router } from "react-router-dom";
import { render } from "@testing-library/react";
import App from "./App";
import "@testing-library/jest-dom/extend-expect";

test("methodToTest should do what I want it to", () => {
    const { getByText } = render(<Router><App /></Router>);
    expect(getByText("You gave me some input")).toBeInTheDocument();
});
Giorgio Polvara - Gpx
  • 12,268
  • 5
  • 53
  • 55
  • Ok, I see that testing the method is against the principles. That makes sense, thank you. It would still be nice to be able to test the method of a component that was in a child (because I need to render it inside a ``), but I see now that it might be better practice to do something like this: https://www.polvara.me/posts/how-to-test-asynchronous-methods/ – Adam D Sep 25 '19 at 14:21
  • RTL has a different approach to tests. It doesn't test the method, it tests that the feature works—mainly by looking at DOM changes – Giorgio Polvara - Gpx Sep 25 '19 at 15:19