diff --git a/src/DebugConfigurationProvider.ts b/src/DebugConfigurationProvider.ts old mode 100644 new mode 100755 index 28db54e9..b0b83d6a --- a/src/DebugConfigurationProvider.ts +++ b/src/DebugConfigurationProvider.ts @@ -1,5 +1,6 @@ import * as vscode from 'vscode'; import * as path from 'path'; +import * as fs from 'fs'; import { toFilePath, @@ -8,6 +9,7 @@ import { escapeRegExp, parseCmdLine, } from './helpers'; +import { platform } from 'os'; export const DEBUG_CONFIG_PLATFORMS = ['windows', 'linux', 'osx']; const testNamePatternRegex = /\$\{jest.testNamePattern\}/g; @@ -204,11 +206,12 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv }; } else { // convert the cmd to absolute path - const program = path.isAbsolute(cmd) + let program = path.isAbsolute(cmd) ? cmd : absoluteRootPath ? path.resolve(absoluteRootPath, cmd) : ['${workspaceFolder}', cmd].join(path.sep); + program = this.adjustProgram(program); const args = [...cmdArgs, ...config.args]; finalConfig = { ...finalConfig, cwd, program, args }; } @@ -218,4 +221,19 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv return finalConfig; } + + // adopt program/command for debug purpose + private adjustProgram(program: string): string { + if (platform() === 'win32' && program.endsWith('\\node_modules\\.bin\\jest.cmd')) { + const newProgram = program.replace( + '\\node_modules\\.bin\\jest.cmd', + '\\node_modules\\jest\\bin\\jest.js' + ); + if (fs.existsSync(newProgram)) { + return newProgram; + } + throw new Error(`failed to find jest binary: ${newProgram}`); + } + return program; + } } diff --git a/tests/DebugConfigurationProvider.test.ts b/tests/DebugConfigurationProvider.test.ts old mode 100644 new mode 100755 index 39573ec6..cbab2242 --- a/tests/DebugConfigurationProvider.test.ts +++ b/tests/DebugConfigurationProvider.test.ts @@ -9,6 +9,7 @@ import { parseCmdLine, } from '../src/helpers'; import * as os from 'os'; +import * as fs from 'fs'; import { makeWorkspaceFolder } from './test-helper'; describe('DebugConfigurationProvider', () => { @@ -193,7 +194,7 @@ describe('DebugConfigurationProvider', () => { ${12} | ${false} | ${'"/dir with space/jest" --arg1=1 --arg2 2 "some string"'} | ${{ cmd: '/dir with space/jest', args: ['--arg1=1', '--arg2', '2', '"some string"'], program: '/dir with space/jest' }} ${13} | ${false} | ${"'/dir with space/jest' --arg1=1 --arg2 2 'some string'"} | ${{ cmd: '/dir with space/jest', args: ['--arg1=1', '--arg2', '2', "'some string'"], program: '/dir with space/jest' }} ${14} | ${false} | ${'jest --arg1 "escaped \\"this\\" string" --arg2 2'} | ${{ cmd: 'jest', args: ['--arg1', '"escaped \\"this\\" string"', '--arg2', '2'], program: '${workspaceFolder}/jest' }} - ${15} | ${true} | ${'.\\node_modules\\.bin\\jest'} | ${{ cmd: 'node_modules\\.bin\\jest', args: [], program: '${workspaceFolder}\\node_modules\\.bin\\jest' }} + ${15} | ${true} | ${'.\\node_modules\\.bin\\jest.cmd'} | ${{ cmd: 'node_modules\\jest\\bin\\jest.js', args: [], program: '${workspaceFolder}\\node_modules\\jest\\bin\\jest.js' }} ${16} | ${true} | ${'..\\jest --config="..\\jest-config.json"'} | ${{ cmd: '..\\jest', args: ['--config=', '"..\\jest-config.json"'], program: '${workspaceFolder}\\..\\jest' }} ${17} | ${true} | ${'jest --config "..\\dir with space\\jest-config.json"'} | ${{ cmd: 'jest', args: ['--config', '"..\\dir with space\\jest-config.json"'], program: '${workspaceFolder}\\jest' }} ${18} | ${true} | ${'\\absolute\\jest --runInBand'} | ${{ cmd: '\\absolute\\jest', args: ['--runInBand'], program: '\\absolute\\jest' }} @@ -204,6 +205,8 @@ describe('DebugConfigurationProvider', () => { if (!canRunTest(isWin32)) { return; } + + (fs.existsSync as jest.Mocked) = jest.fn().mockReturnValue(true); // eslint-disable-next-line @typescript-eslint/no-unused-vars const { args, program, windows, ...restConfig } = config; const sut = new DebugConfigurationProvider(); @@ -229,6 +232,31 @@ describe('DebugConfigurationProvider', () => { const sut = new DebugConfigurationProvider(); expect(() => sut.withCommandLine(workspace, cmdLine)).toThrow('invalid cmdLine'); }); + describe('on win32, should throw error if the raw jest binary can not be found', () => { + beforeEach(() => { + (os.platform as jest.Mocked) = jest.fn().mockReturnValue('win32'); + }); + afterEach(() => { + (os.platform as jest.Mocked).mockReset(); + }); + it.each` + exists + ${true} + ${false} + `('file exists = $exists', ({ exists }) => { + (fs.existsSync as jest.Mocked) = jest.fn().mockReturnValue(exists); + const sut = new DebugConfigurationProvider(); + if (!exists) { + expect(() => + sut.withCommandLine(workspace, 'whatever\\node_modules\\.bin\\jest.cmd') + ).toThrow(); + } else { + expect(() => + sut.withCommandLine(workspace, 'whatever\\node_modules\\.bin\\jest.cmd') + ).not.toThrow(); + } + }); + }); it.each` cmd | cArgs | appendExtraArg ${'yarn'} | ${['test']} | ${false}