eslint-plugin-testing-library: Rules do not work with custom name library name

I love the no-debug rule, however, it doesn’t work if you’re using a custom local library name in order to, for example, provide a custom render function to the rest of your code.

I agree that the library name is no longer @testing-library/react, for example, and could be anything, so the rule doesn’t find a match, but because customizing the render function is in the docs, and I presume quite standard practice, it makes this rule an immediate non-starter, which is a shame since the rule would be really nice to have.

Seems like the rule needs an option, similar to the existing renderFunctions option, that we can use to specify the name of our import. In my case, it’s import ... from 'testingUtility'.

import { screen } from '@testing-library/react';
...
screen.debug(); // IS a lint error

however,

import { screen } from 'testingUtility';
...
screen.debug(); // is NOT a lint error -- and should be

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 21 (15 by maintainers)

Most upvoted comments

@VED-StuartMorris I have more good news for you! We have added another shared setting to customize on which files you want the plugin to be ran based on a regexp. By default it will report all files with suffix .test or .spec, so you don’t need to set up anything if that works for you. However, let’s say you are using .test files for Testing Library tests and .spec for Cypress tests, you can set this new shared setting to run the plugin only on .test files. You’ll have more details and instructions on final v4 docs.

Furthermore, this would work on any import from the utils file?

Yes, basically for all utils matching Testing Library ones: queries, render, screen, waitFor, etc. So that example you mentioned will be automatically reported for you just by upgrading to v4.

I think we also need to check default testing library imports (e.g. @testing-library/react) even if the user sets a custom testing library module through ESLint settings. In my code base, the custom module only expose alternate render methods. So if we want the default render, we import from testing library itself. But if we want a custom one, we import from our own module so we have mixed imports.

I don’t think this makes the implementation more difficult, but we need to append the custom module to the list of modules to check, rather than check one or the other.

This should be fixed on v4.0.0

The release is available on:

@nickmccurdy The way I was thinking of it, with the config option, is that someone would provide the alternate name for the React Testing Library (RTL) module being used. In my case, that would be “testingUtility”.

I will guess that not everyone will configure Jest as I have, so they would have imports like this instead (for example):

import { render} from 'testingUtility'; // vs
 
import { render } from '../../../test/testingUtility'; // or
const { render } = require('../../../test/testingUtility');

In that case, I was thinking that it’s still the module name that would matter, not the path. So you could configure the name as “testingUtility” and it would work in all cases above.

I also think it’s completely reasonable to make the assumption that the module’s interface is the same as (or a superset of) RTL’s interface for this config option. So if there’s a reference to render or debug from that module, the rules give those tokens the same connotation as if the import was directly from RTL.

(BTW, my local testingUtility is a superset of RTL because it also provides about 6 other alternate render methods for various use cases, some examples being lightThemeRender, darkThemeRender, as well as a docsRender which we use for unit testing our generated docs system that happens to use different providers. So have already used the config options for no-debug to let it know about these alternate names, and it works great, when the import is @testing-library/react, of course 😉 .)

Of course, it would be good to state this assumption as a warning for this config option.

I deleted my comment originally because I forgot that you mentioned the custom render function, but this does help to add some more clarity to different use cases, thanks! Another idea is that you might need to adjust TypeScript types for passed props/context/etc. by wrapping the testing library functions in types with different interfaces (this used to be the way to provide themes to Styled Components before they implemented type augmentation).

Given all these use cases, I guess we do need a config. We would have to resolve the modules to search the dependency tree for testing libraries, and even with that you couldn’t easily publish a fork. It would also be difficult to accurately determine whether a module is meant to replace testing library, or is just some testing utility that happens to import a method from it (in which case you wouldn’t want your linter telling you to use functions from it that don’t exist).

I still think there’s another problem even with a custom config though: The module wrapping testing library would have to have the same API with the same semantics, otherwise rules might recommend the wrong methods, methods may not exist, or advice may not be relevant. I guess there isn’t really a way around this beyond telling users to write their own custom ESLint rules (which you can do locally without publishing a separate package), so we might want to warn that these rules are only designed to be used with a wrapper that follows the same API and semantics, and possibly link to the ESLint docs for custom rules.

@stefcameron Ah yes, that is what I was thinking of, thanks

I think ESLint Shared Settings, as @timdeschryver points out, would be a good way to go to solve this for all rules. Another example is eslint-plugin-react, see configuration options