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".
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.
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.
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 ().
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.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With