Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError: Expected container to be an Element, a Document or a DocumentFragment but got string

I'm trying to run the below testcase using RTL , and the test is failing with the error "TypeError: Expected container to be an Element, a Document or a DocumentFragment but got string.". I tried searching for solution but couldn't find one .

describe("Feedback Commponent",()=>{
  it('should throw error when feedback textbox is empty', () => {
    const { getByLabelText} = render(<Contact />);

    fireEvent.change(getByLabelText('Feedback'), {
      target: { value: '' },
    });

    fireEvent.blur(getByLabelText('Feedback'));
    debug();

    expect(getByTestId('feedback-error')).toBe(
      'Please Enter Your Feedback'
    );
  });
});

The above snippet is suppose to test the feedback form , to be specific only the feedback text box , when it is empty and when user goes out of focus from the textbox ,there should be an error stating "Please Enter Your Feedback".

like image 915
novice Avatar asked Aug 10 '20 20:08

novice


People also ask

Why createroot() target container is not a DOM element?

The error "createRoot () Target container is not a DOM element" is mostly caused by two reasons: When we pass the wrong id of the HTML div tag to the "document.getElementById ()" method. The React script was placed before the div tag with id in the index.html file.

What does the error createroot(...) mean?

The error "createRoot (...): Target container is not a DOM element" occurs for multiple reasons: Passing an incorrect id to the document.getElementById () method. Placing the react script file above the code that creates the div element. Incorrectly configuring webpack's index.html file. Here is an example of how the error occurs.

What is documentfragment in Node JS?

Functionally equivalent to Document.getElementById (). A common use for DocumentFragment is to create one, assemble a DOM subtree within it, then append or insert the fragment into the DOM using Node interface methods such as appendChild (), append (), or insertBefore ().

What is the difference between document and document fragment?

It is used as a lightweight version of Document that stores a segment of a document structure comprised of nodes just like a standard document. The key difference is due to the fact that the document fragment isn't part of the active document tree structure. Changes made to the fragment don't affect the document.


2 Answers

It seems that you imported getByTestId method straight from testing library instead of destructuring it from render like you did with getByLabelText. getByTestId, according to the docs is:

getByTestId(
  // If you're using `screen`, then skip the container argument:
  container: HTMLElement,
  text: TextMatch,
  options?: {
    exact?: boolean = true,
    normalizer?: NormalizerFn,
  }): HTMLElement

So it expects the first argument to be the HTML container, hence the error. One solution would be to destructure getByTestId as well:

const { getByLabelText, getByTestId } = render(<Contact />);

Another one is to use screen, as suggested by the docs:

import { screen } from '@testing-library/react';
...

expect(screen.getByTestId('feedback-error')).toBe(
  'Please Enter Your Feedback'
);

In which case the first 'container' argument is skipped and the string 'feedback-error' is treated like test id 'text' argument. Docs: https://testing-library.com/docs/queries/bytestid

like image 90
Infermath Avatar answered Oct 13 '22 05:10

Infermath


I resolved the issue by changing the assertion to

expect(getByText('Please Enter Your Feedback')).toBeInTheDocument();

from

 expect(getByTestId('feedback-error')).toBe('Please Enter Your Feedback');

Also I noticed that I had setupTest.js file with

import '@testing-library/jest-dom/extend-expect';

missing , which adds custom jest matchers for asserting on DOM nodes, so after adding the above changes my test case passed

like image 35
novice Avatar answered Oct 13 '22 05:10

novice