scottcorgan / tap-out

A different tap parser
MIT License
23 stars 28 forks source link

Fails on coverage output if name of a class in a subdirectory is truncated #42

Open aral opened 3 years ago

aral commented 3 years ago

Summary

When your tests import a class with 33 or more letters in its name (e.g., ThisIsAClassWith33LettersInItsName from a subdirectory of your project, tap-out detects it as an error output end token instead of a truncated class name and exits with error code 1.

To reproduce

Run the following example, which simulates the scenario described above:

import tapOut from 'tap-out'

const parser = tapOut()
parser.on('output', function (output) {
  console.log(output)
})

parser.write('  ...IsAClassWith33LettersInItsName.js |     100 |      100 |     100 |     100 |')
parser.end()

What should happen

It should be parsed properly as a comment and you should see the following output:

{
  tests: [],
  asserts: [],
  versions: [],
  results: [],
  comments: [
    {
      type: 'comment',
      raw: '  ...IsAClassWith33LettersInItsName.js |     100 |      100 |     100 |     100 |',
      test: 0
    }
  ],
  plans: [],
  pass: [],
  fail: [],
  errors: []
}

What actually happens

It gets detected as an error output end token and, in this case, the above program crashes with the following error:

/home/aral/sandbox/tap-out-bug/node_modules/tap-out/index.js:131
    lastAssert.error.raw = this.lastAsserRawErrorString.replace(/\s+$/g, '');
               ^

TypeError: Cannot read property 'error' of undefined
    at Parser._handleError (/home/aral/sandbox/tap-out-bug/node_modules/tap-out/index.js:131:16)
    at Parser.handleLine (/home/aral/sandbox/tap-out-bug/node_modules/tap-out/index.js:48:8)
    at Stream.<anonymous> (/home/aral/sandbox/tap-out-bug/node_modules/tap-out/index.js:256:14)
    at Stream.emit (events.js:315:20)
    at drain (/home/aral/sandbox/tap-out-bug/node_modules/through/index.js:36:16)
    at Stream.stream.queue.stream.push (/home/aral/sandbox/tap-out-bug/node_modules/through/index.js:45:5)
    at emit (/home/aral/sandbox/tap-out-bug/node_modules/split/index.js:37:14)
    at Stream.<anonymous> (/home/aral/sandbox/tap-out-bug/node_modules/split/index.js:60:7)
    at _end (/home/aral/sandbox/tap-out-bug/node_modules/through/index.js:65:9)
    at Stream.stream.end (/home/aral/sandbox/tap-out-bug/node_modules/through/index.js:74:5)

Why it happens

The culprit is the conditional that detects the error output end token:

function isErrorOutputEnd (line) {
  return line.indexOf('  ...') === 0;
}

The fix

I’m going to prepare a pull request but since this package is currently not being maintained, you might just want to implement the one-line fix yourself in your own fork:

function isErrorOutputEnd (line) {
  return line === '  ...';
}

Background

I discovered this bug while using tap-nyc, which uses tap-out as a dependency. If you pipe your coverage results from the nyc or c8 code coverage tools and a class in your projects satisfies the requirements, your process will exit with an error.