Debug Jest Spec In VsCode - Error missing ) after argument list
Tags: jest, worknote, vscode
Published: 2022-01-29 18:52:08

<sub><sup>Photo by <a href="https://unsplash.com/@flowforfrank?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Ferenc Almasi</a> on <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
  </sup></sup>

## Scenario

Trying to debug a Jest spec in Vscode, leads to an error:

```
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
          ^^^^^^^
SyntaxError: missing ) after argument list
```

## Solution

There is a problem in the configuration. The default config tries to run the sh shell script of jest as a node program.

Instead, we can skip the sh jest script and run directly the jest nodejs script.

Instead of: 

```js
"${workspaceRoot}/node_modules/.bin/jest"
```

We replace it with:

```js
"${workspaceRoot}/node_modules/jest/bin/jest.js",
```

```js
   {
      "name": "vscode-jest-tests",
      "type": "node",
      "request": "launch",
      "runtimeArgs": [
        "--inspect-brk",
        "${workspaceRoot}/node_modules/jest/bin/jest.js",
        "--runInBand"
      ],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "port": 9229
    }
```

## Solution Walkthrough

In this case, I'm using `pnpm`. `pnpm` is [creating a bin](https://github.com/pnpm/pnpm/blob/701ea07461eec2c1802c5b8f5a517e64419e7fe6/packages/link-bins/src/index.ts#L215) that is a bash script that calls node to run the actual bin nodejs script.

*node_modules/.bin/jest*

```bash
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -z "$NODE_PATH" ]; then
  export NODE_PATH=".........."
else
  export NODE_PATH="$NODE_PATH:/........"
fi
if [ -x "$basedir/node" ]; then
  exec "$basedir/node"  "$basedir/../jest/bin/jest.js" "$@"
else
  exec node  "$basedir/../jest/bin/jest.js" "$@"
fi
```

[pnpm linkbin package](https://github.com/pnpm/pnpm/blob/701ea07461eec2c1802c5b8f5a517e64419e7fe6/packages/link-bins/src/index.ts#L215)

```js
async function linkBin (cmd: CommandInfo, binsDir: string, opts?: { extendNodePath?: boolean }) {
  const externalBinPath = path.join(binsDir, cmd.name)

  try {
    let nodePath: string[] | undefined
    if (opts?.extendNodePath !== false) {
      nodePath = await getBinNodePaths(cmd.path)
      const binsParentDir = path.dirname(binsDir)
      if (path.relative(cmd.path, binsParentDir) !== '') {
        nodePath = union(nodePath, await getBinNodePaths(binsParentDir))
      }
    }
    await cmdShim(cmd.path, externalBinPath, {
      createPwshFile: cmd.makePowerShellShim,
      nodePath,
      nodeExecPath: cmd.nodeExecPath,
    })
  } catch (err: any) { // eslint-disable-line
    if (err.code !== 'ENOENT') {
      throw err
    }
    globalWarn(`Failed to create bin at ${externalBinPath}. The source file at ${cmd.path} does not exist.`)
    return
  }
```

[cmd-shim](https://github.com/pnpm/cmd-shim/blob/51909b72a85ba5c5ed796eafed570a6beb4fa520/src/index.ts#L425)

```js
  let sh = `\
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")
case \`uname\` in
    *CYGWIN*) basedir=\`cygpath -w "$basedir"\`;;
esac
```

So the bin that the `jest` `vscode` [launch configuration](https://code.visualstudio.com/Docs/editor/debugging) is targeting the bash script. The runner is set as a nodejs runner script. The script that it is trying to run is a `sh` script. That is the problem. 

`launch.json`

```js
   "type": "node",
    ...
    "${workspaceRoot}/node_modules/.bin/jest"
```

We can find the atrribute for the `launch.json` [here](https://code.visualstudio.com/Docs/editor/debugging#_launchjson-attributes)

So, instead of running the sh script, we redirect the launcher to run directly the jest nodejs script.