core: Command parsing hangs under unit test

We have been using oclif v1 and unit test our CLI using jest. We follow the instruction in the oclif docs to use the static Command.run inside tests. When attempting to migrate the project from v1 to core, several of the tests had timeout failures which signified a hanging handler. I dug into the parsing differences between v1 and core and found that core has a new feature which falls back to reading from stdin if there are no arguments specified. This causes issues as our CLI has several commands which have only optional arguments. I am not aware of this being a known breaking change, as it isn’t mentioned on the migration guide.

Bug

I believe a summary of the issue is that calling Command.run() without args under test causes a hang at this line in the parser (waiting for input that will never arrive).

Current (core) behavior

Here is an example of one of our tests that is hanging with core.

await expect(AppRegisterCommand.run()).resolves.not.toThrow() // note the omitted run args

It fails with the following.

: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Timeout

The test just below it however passes on the same command since it includes args.

await expect(AppRegisterCommand.run([appId])).resolves.not.toThrow() // including any arg works around the hang

✕ calls selectFromList with correct config (5005 ms) ✓ calls correct endpoint for registration and logs success (18 ms)

Environment

@oclif/core”: "^1.0.11 " darwin-x64 node-v12.18.1

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17 (10 by maintainers)

Commits related to this issue

Most upvoted comments

@john-u I believe I have reproduced this using a simpler project. Command in question does define, so not sure if the timeout I am seeing is the same that you are seeing.

static args = [{name: 'person', description: 'Person to say hello to', required: true}]

Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error:

      2 | 
      3 | describe('hello', async () => {
    > 4 |   it('runs hello cmd', async () => {
        |   ^
      5 |     await Hello.run([])
      6 |   })
      7 | })

@john-u I tried the suggestions of adding the [] to run. Now the test fails with a timeout.

: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.
Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error: 

I will discuss this with team mates, next week.