"istanbul ignore next" command seems to be ignored
Asked Answered
I

3

7

I'm trying to use Jest to test my code. It was working quite fine until I tried to exclude a class method from the tests.

The querySelector() call is the reason why I want to skip this method from being tested ("document" is obviously null unless I run the script in the browser)

I tried this solution, which seems to be the most suggested one:

  /* istanbul ignore next */
  appendNewInputFields() {

    const howMany = Number(document.querySelector('#items-to-add').value);
    
    [...Array(howMany)].forEach( i => {
      const newInputField = this.createNewItemInputField();
      this.inputItemsContainerNode.append(newInputField);
    });
  }

But the test keeps failing and the line /* istanbul ignore next */ seems to be ignored.

I've also tried putting the comment between the function signature and its body (as was suggested somewhere here on SO), but no luck:

 FAIL  js/DOMManager.test.js
  ● Test suite failed to run

    TypeError: Cannot read property 'value' of null

      135 |   appendNewInputFields() /* istanbul ignore next */ {
      136 |
    > 137 |     const howMany = Number(document.querySelector('#items-to-add').value);
          |                            ^
      138 |     

I've read around that this might be related to babel-plugin-istanbul. I've tried

npm --save-dev uninstall babel-plugin-istanbul

which in the terminal returned:

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

removed 18 packages and audited 521 packages in 2.178s

but the folder babel-plugin-istanbul is still present in /node_modules/ inside my working folder and the test keeps failing as if nothing changed.

If I comment out the body of the function, the other test suites work perfectly. If I try to apply the ignore next command to any other part of the code, the tests pass just fine and the line is completely ignored.

If I try to manually delete the /babel-plugin-istanbul/ folder (from the /node_modules/ in my working folder), Jest stops working.

(This is the first time I installed Node.js, and I did it only because I wanted to start unit testing with Jest. I'm pointing this out because these are my first steps venturing out of the vanilla world. I don't know how to deal with Node.js nor npm, I just launched a couple commands to install it, I wrote a few tests for Jest and they all immediately worked fine. I'm not using any other framework, I'm trying to stick to vanilla JS as much as possible.)

----------------------- Edit:

I tried changing the code to this:


  appendNewInputFields() {
    // TODO solve the istanbul ignore issue
    
    let howMany;

    /* istanbul ignore if */
    if(document != null) {
      howMany = Number(document.querySelector('#items-to-add').value);
    
      [...Array(howMany)].forEach( i => {
        const newInputField = this.createNewItemInputField();
        this.inputItemsContainerNode.append(newInputField);
      });

      console.log("added " + howMany + " input fields");
    }
  }

I keep getting

 FAIL  js/DOMManager.test.js
  ● Test suite failed to run

    TypeError: Cannot read property 'value' of null

      139 |     /* istanbul ignore if */
      140 |     if(document != null) {
    > 141 |       howMany = Number(document.querySelector('#items-to-add').value);
          |                        ^
      142 |     
      143 |       [...Array(howMany)].forEach( i => {
      144 |         const newInputField = this.createNewItemInputField();

I'm totally clueless at this point. Given the conditional, "document" should be null and that block entirely skipped, but it keeps failing the test.

The same code works exactly as intended when run in the browser.

Insensibility answered 8/3, 2021 at 15:15 Comment(0)
I
4

So I made a few tests in a blank new folder, and it finally struck me.

Apparently I had misunderstood the purpose of /* istanbul ignore next */.

Its function is not to skip code from being executed during the tests, but rather prevent that portion of code to be taken into account when determining the amount of total code that has been tested. The code runs (if there is anything calling that function), but those lines just don't count when Jest sums up the amount of lines it tested (which is the purpose of --coverage, I guess). If an error occurs, it is thrown as it would normally be.

My problem wasn't really related to Jest nor the istanbul package. I feel pretty dumb realizing this now, but what I needed was just proper exception handling.

I implemented a few old fashioned try/catch blocks: now everything is tested smoothly and the istanbul ignore directive correctly behaves as expected (now that I know what to expect, that is): functions that are not tested and flagged to be ignored, they just don't appear in the final coverage report.

I hope this helps anybody who might stumble in my same misunderstanding.

Of course, if anybody more competent than me can confirm this interpretation or has any suggestion or further explanation, it would obviously be much appreciated.

Insensibility answered 9/3, 2021 at 11:7 Comment(3)
You're correct – istanbul is a code coverage package. Just be careful with your try/catches; you might be catching an exception that you're trying to test. An early-exit like if(!window) return; in your test case would be better.Distinctive
But wouldn't window always be falsy and prevent any kind of testing related to DOM manipulation? Come to think of it, this is actually what I was trying to do with if(document != null), only I had it in the .js file instead of .test.js and that's probably why it didn't work. Thanks a lot for your insight, I will look further into this.Insensibility
Window is truthy in the browser or when e. g. Jsdom has been set up globally.Distinctive
C
2

This might also happen if your bundling tool (esbuild, for instance) removes comments, therefore istanbul does not see them.

If that's the case, you might want to change your bundling tool to something like terser (make sure that comments are not omitted there, too) or adjust minification options of the bundling tool you use.

This is how it would look like if you use Vite:

build: {
  minify: 'terser',
  terserOptions: {
    format: {
      comments: 'all', // or regular expression /istanbul\signore\s/
    },
  },
},
Champlin answered 3/5, 2022 at 12:14 Comment(0)
S
-3

I was with the same error with window.alert command with jest:

ReferenceError: alert is not defined

  4 |
  5 | /* istanbul ignore next */
> 6 | alert(helloWorld());
    | ^
  7 |

so I tried to use try-catch and SUCCESS!

before:

alert(helloWorld());

after:

const alerta = () => {
  try {
    return alert(helloWorld());
  } catch (error) {
      return false;
  }
}

testes:

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Scholastic answered 12/2, 2022 at 3:15 Comment(1)
Never do this. You could just as well write if (true) return true; I have no idea why you would want to use alert in a unit test, but if you do, you should mock the behaviour that you expect to happen instead of flat out ignoring.Malfeasance

© 2022 - 2024 — McMap. All rights reserved.