avajs / ava

Node.js test runner that lets you develop with confidence 🚀
MIT License
20.74k stars 1.41k forks source link

Feature request: Allow disabling of command line animation #1859

Closed christroutner closed 6 years ago

christroutner commented 6 years ago

Description

It would be great if there was a configuration setting to disable the animation on the command line. When piping the stdout to a file, you end up with this as output:

...
⠏  
⠋  
⠙  
⠹  
⠸  
⠼  
⠴  
⠦  
⠧  
⠇  
⠏  
⠋  
⠙  
⠹  
⠸  
⠼  
⠴  
⠦  
⠧  
⠇  
⠏  
⠋  
⠙  
⠹  
⠸  
...

The issue arose because I'm trying to pipe the output of an extensive ava test to a log file for later analysis.

Relevant Links

This stack overflow thread was the only mention of the command line animation that I could find. Followed the links in it, as well as additional googling, and couldn't find any solutions for disabling the animation.

Environment

Linux

forresst commented 6 years ago

I think this can be handled by ora. The following code should be added at the beginning of the frame() method:

    frame() {
+       if (!this.stream.isTTY) {
+           return '';
+       }

        const frames = this.spinner.frames;
        let frame = frames[this.frameIndex];

        if (this.color) {
            frame = chalk[this.color](frame);
        }

        this.frameIndex = ++this.frameIndex % frames.length;

        return frame + ' ' + this.text;
    }

@sindresorhus @novemberborn your opinion ?

forresst commented 6 years ago

Note, it is also necessary that the sindresorhus/ora#82 is merged

novemberborn commented 6 years ago

We already check for a TTY in the reporters, though this broke in 1.0.0-beta.5. I just ran this in my terminal and it looks like Node.js (at least 10.6 on macOS) detects the output being piped:

❯ node -p "process.stdout.isTTY" | cat
undefined

~
❯ node -p "process.stdout.isTTY"
true

So I believe there is no issue when using 1.0.0-beta.6. I'll close this for now, but happy to reopen.

Which version are you using @christroutner?

christroutner commented 6 years ago

I'm using node v8.11.3.

Here is a snippet of the code I'm trying to use:

    // Create a file to output results.
    const test1Log = fs.createWriteStream(`${LOG_DIR}${TEST1_LOG}`);

    // Pipe the output to the log file and do not block.
    const test1Child = execa.shell(RUN_HAPPY_PATH_PATENT);
    test1Child.stdout.pipe(test1Log);
    test1Child.stderr.pipe(test1Log);

So I'm actually trying to pipe the output from execa, which is the output from and SSH command, which is the output from Ava.

So @novemberborn you think all I need to do is upgrade to node v10? I'll give that a go.

christroutner commented 6 years ago

I upgraded to node v10 and I got the same output.

novemberborn commented 6 years ago

Ah. I suspect that the spawned process inherits the TTY behavior from the process that's calling it. In your case, try running execa.shell(RUN_HAPPY_PATH_PATENT, {stdout: test1Log, stderr: test1Log}). Or since you're using shell(): execa.shell(RUN_HAPPY_PATH_PATENT + '|cat').

I'm reluctant to add CLI flags to disable this behavior, since the TTY behavior is (I believe) the standard way this should behave.

christroutner commented 6 years ago

Those were good ideas. I tried both.

Using execa.shell(RUN_HAPPY_PATH_PATENT, {stdout: test1Log, stderr: test1Log}) didn't work at all. I included the error output at the bottom of this comment.

Using the |cat hack didn't change the output at all. The log file is still showing the same output, as illustrated at the top of this Issue. I think the TTY behavior is getting lost along the chain of output. I believe the source of problem is the output from Ava, not the output of execa.

Is there any way to force the isTTY setting that Ava detects?

Here's the error I got when trying execa.shell(RUN_HAPPY_PATH_PATENT, {stdout: test1Log, stderr: test1Log}):

ypeError [ERR_INVALID_OPT_VALUE]: The value "WriteStream {
  _writableState:
   WritableState {
     objectMode: false,
     highWaterMark: 16384,
     finalCalled: false,
     needDrain: false,
     ending: false,
     ended: false,
     finished: false,
     destroyed: false,
     decodeStrings: true,
     defaultEncoding: 'utf8',
     length: 33,
     writing: true,
     corked: 0,
     sync: false,
     bufferProcessing: false,
     onwrite: [Function: bound onwrite],
     writecb: [Function: nop],
     writelen: 33,
     bufferedRequest: null,
     lastBufferedRequest: null,
     pendingcb: 1,
     prefinished: false,
     errorEmitted: false,
     emitClose: false,
     bufferedRequestCount: 0,
     corkedRequestsFree:
      { next: null,
        entry: null,
        finish: [Function: bound onCorkedFinish] } },
  writable: true,
  _events:
   { open: { [Function: bound onceWrapper] listener: [Function] } },
  _eventsCount: 1,
  _maxListeners: undefined,
  path: '/var/www/html/happy-path-patent-output.txt',
  fd: null,
  flags: 'w',
  mode: 438,
  start: undefined,
  autoClose: true,
  pos: undefined,
  bytesWritten: 0,
  closed: false }" is invalid for option "stdio"
    at internal/child_process.js:936:13
    at Array.reduce (<anonymous>)
    at _validateStdio (internal/child_process.js:863:17)
    at ChildProcess.spawn (internal/child_process.js:300:11)
    at Object.spawn (child_process.js:528:9)
    at module.exports (/home/trout/welo-docker-images/images/pantheon-ubuntu/bvt/src/runtests/node_modules/execa/index.js:204:26)
    at handleShell (/home/trout/welo-docker-images/images/pantheon-ubuntu/bvt/src/runtests/node_modules/execa/index.js:119:9)
    at Function.module.exports.shell (/home/trout/welo-docker-images/images/pantheon-ubuntu/bvt/src/runtests/node_modules/execa/index.js:327:39)
    at runTests (/home/trout/welo-docker-images/images/pantheon-ubuntu/bvt/src/runtests/index.js:145:30)
(node:697) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:697) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I tried various tweeks around setting stdio for the file write stream, but couldn't improve the situation. I'm just not very familiar with the inner workings of this low-level behavior.

christroutner commented 6 years ago

I tried forcing process.stdout.isTTY = false at the top of the ava test file, but that didn't have any affect on the command line animation.

christroutner commented 6 years ago

I just noticed the ava test-file.js > output.log produces an empty file. Hmm...

I was thinking that I could pipe the ava output to a file and then just retrieve the file, rather than trying to read the output over SSH.

christroutner commented 6 years ago

I figured it out! I just used the --tap command line argument with ava. That fixed all the log file output issues.