How to test next/script with testing-library?
Asked Answered
A

2

6

My react component renders a <script> tag using nextJS Head. When trying to query the element with testing-libary's getByTestId method and I get the message below:

TestingLibraryElementError: Unable to find an element by: [data-testid="keen-to-test"]
Ignored nodes: comments, <script />, <style />

Is there a way to include script in the output or should I use a different strategy to verify if my script is injected? thanks in advance

component

import Head from 'next/head';

const FancyScript = ({src}) => {
  if (src) {
   return (
     <Head>
      <script
        data-testid="keen-to-test"
        type="text/javascript"
        async
        src={src}
      </script>
     </Head>
   )
  }
  return null;
}

test

import { render } from '@testing-library/react';
import FancyScript from '/fancy-location';

it('return some fancy', () => {
    const { getByTestId } = render(<FancyScript src="real_src_here" />);
    expect(getByTestId('keen-to-test')).toHaveAttribute('src', 'real_src_here');
  });
Acervate answered 15/7, 2021 at 11:47 Comment(2)
good point @slideshowp2, I hid some implementation detail to set a better focus on the question. I'm using nextjs and render the script tag into the head section of my HTML doc.Acervate
You could try mocking next/head during your test.Indorse
A
1

What I did was something like this:

Basically, I created the mock for the <Script> component. So I render the Scripts inside the MyComponentContainingTheScripts and using the mock the real component coming from next is replaced.

In fact, I think <Script> does not support the data-testid but using the mock you can use it, at the end we need to test the implementation not the Scriptcomponent itself since it is a third-party component, They should handle the tests for it.

    jest.mock('next/script', () => {
      // eslint-disable-next-line react/display-name, react/prop-types
      return function ({ children, 'data-testid': dataTestId, ...props }) {
        return (
          <script data-testid={dataTestId} {...props}>
            {children}
          </script>
        );
      };
    });

    it('should include the config.js and loader.js files', async () => {
      render(
        <Provider store={global.createStoreWithInitialState({})}>
          <MyComponentContainingTheScripts /> 
        </Provider>
      );

      const elementOne = await screen.findByTestId('someTestId');
      const elementTwo = await screen.findByTestId('someSecondTestId');

      expect(elementOne).toBeInTheDocument();
      expect(elementTwo).toBeInTheDocument();
    });
Abet answered 15/8, 2023 at 21:47 Comment(0)
G
0

One approach is to test the state of the document. For example:

it('Has the correct src', () => {
  // I'm using `next/script` here, but it should also work with `next/head`
  render(<Script src="myScript.js" />);

  expect(document.querySelector('script')).toHaveAttribute('src', 'myscript.js');
});
Galimatias answered 4/8, 2022 at 8:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.