Skip to content

Commit 53f9e3d

Browse files
authored
Merge pull request jest-community#332 from seanpoulter/feature/jest-community#313/Fix-regression-in-support-for-react-scripts
Fix regression detecting create-react-app
2 parents 5b24189 + 49f430f commit 53f9e3d

9 files changed

Lines changed: 181 additions & 63 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Bug-fixes within the same version aren't needed
1010
text editor - seanpoulter
1111
* Restart Jest with --watchAll when --watch is not supported without git/hg
1212
- seanpoulter
13+
* Fix regression in handling workspaces that have been bootstrapped with
14+
create-react-app - seanpoulter
1315
1416
-->
1517

src/DebugConfigurationProvider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as vscode from 'vscode'
2-
import { getTestCommand, isCRATestCommand } from './helpers'
2+
import { getTestCommand, isCreateReactAppTestCommand } from './helpers'
33

44
export class DebugConfigurationProvider implements vscode.DebugConfigurationProvider {
55
private fileNameToRun: string = ''
@@ -63,7 +63,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
6363
}
6464

6565
const testCommand = folder && getTestCommand(folder.uri.fsPath)
66-
if (isCRATestCommand(testCommand)) {
66+
if (isCreateReactAppTestCommand(testCommand)) {
6767
const craCommand = testCommand.split(' ')
6868
// Settings specific for projects bootstrapped with `create-react-app`
6969
debugConfiguration.runtimeExecutable = '${workspaceFolder}/node_modules/.bin/' + craCommand.shift()

src/JestExt.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Settings, ProjectWorkspace, JestTotalResults } from 'jest-editor-suppor
44
import { matcher } from 'micromatch'
55

66
import * as decorations from './decorations'
7-
import { IPluginSettings } from './IPluginSettings'
7+
import { IPluginSettings } from './Settings'
88
import * as status from './statusBar'
99
import {
1010
TestReconciliationState,

src/Settings/index.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
jest.unmock('../index')
2+
import { isDefaultPathToJest } from './index'
3+
4+
describe('isDefaultPathToJest', () => {
5+
it('returns true when the value is null', () => {
6+
expect(isDefaultPathToJest(null)).toBe(true)
7+
})
8+
9+
it('returns true for the legacy default ""', () => {
10+
expect(isDefaultPathToJest('')).toBe(true)
11+
})
12+
13+
it('returns false otherwise', () => {
14+
expect(isDefaultPathToJest('')).toBe(false)
15+
})
16+
})
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { TestState } from './DebugCodeLens'
1+
import { TestState } from '../DebugCodeLens'
22

33
export interface IPluginSettings {
44
autoEnable?: boolean
@@ -17,3 +17,11 @@ export interface IPluginSettings {
1717
showCoverageOnLoad: boolean
1818
coverageFormatter: string
1919
}
20+
21+
export function isDefaultPathToJest(str) {
22+
return str === null || str === ''
23+
}
24+
25+
export function hasUserSetPathToJest(str) {
26+
return !isDefaultPathToJest(str)
27+
}

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as path from 'path'
55
import { extensionName } from './appGlobals'
66
import { pathToJest, pathToConfig } from './helpers'
77
import { JestExt } from './JestExt'
8-
import { IPluginSettings } from './IPluginSettings'
8+
import { IPluginSettings } from './Settings'
99
import { registerStatusBar } from './statusBar'
1010
import { registerSnapshotCodeLens, registerSnapshotPreview } from './SnapshotCodeLens'
1111
import { registerCoverageCodeLens } from './Coverage'

src/helpers.ts

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { platform } from 'os'
22
import { existsSync, readFileSync } from 'fs'
33
import { normalize, join } from 'path'
44

5-
import { IPluginSettings } from './IPluginSettings'
5+
import { IPluginSettings, hasUserSetPathToJest } from './Settings'
66

77
/**
88
* Known binary names of `react-scripts` forks
@@ -11,7 +11,7 @@ const createReactAppBinaryNames = ['react-scripts', 'react-native-scripts', 'rea
1111

1212
/**
1313
* Tries to read the test command from the scripts section within `package.json`
14-
*
14+
*
1515
* Returns the test command in case of success,
1616
* `undefined` if there was an exception while reading and parsing `package.json`
1717
* `null` if there is no test script
@@ -29,24 +29,24 @@ export function getTestCommand(rootPath: string): string | undefined | null {
2929
}
3030
}
3131

32-
/**
32+
/**
3333
* Checks if the supplied test command could have been generated by create-react-app
3434
*/
35-
export function isCRATestCommand(testCommand: string): boolean {
35+
export function isCreateReactAppTestCommand(testCommand: string): boolean {
3636
return testCommand && createReactAppBinaryNames.some(binary => testCommand.indexOf(binary + ' test') === 0)
3737
}
3838

3939
/**
4040
* Checks if the project in `rootPath` was bootstrapped by `create-react-app`.
4141
*/
42-
function isBootstrappedWithCRA(rootPath: string): boolean {
42+
function isBootstrappedWithCreateReactApp(rootPath: string): boolean {
4343
const testCommand = getTestCommand(rootPath)
4444
if (testCommand === undefined) {
4545
// In case parsing `package.json` failed or was unconclusive,
4646
// fallback to checking for the presence of the binaries in `./node_modules/.bin`
4747
return createReactAppBinaryNames.some(binary => hasNodeExecutable(rootPath, binary))
4848
}
49-
return isCRATestCommand(testCommand)
49+
return isCreateReactAppTestCommand(testCommand)
5050
}
5151

5252
function hasNodeExecutable(rootPath: string, executable: string): boolean {
@@ -56,29 +56,32 @@ function hasNodeExecutable(rootPath: string, executable: string): boolean {
5656
}
5757

5858
/**
59-
* Handles getting the jest runner, handling the OS and project specific work too
59+
* Handles getting the jest runner, handling the OS and project specific work too
6060
*
6161
* @returns {string}
6262
*/
63-
export function pathToJest(pluginSettings: IPluginSettings) {
64-
if (pluginSettings.pathToJest) {
65-
if (isBootstrappedWithCRA(pluginSettings.rootPath)) {
66-
return 'npm test --'
67-
}
68-
return normalize(pluginSettings.pathToJest)
63+
export function pathToJest({ pathToJest, rootPath }: IPluginSettings) {
64+
if (hasUserSetPathToJest(pathToJest)) {
65+
return normalize(pathToJest)
6966
}
7067

71-
const platform = process.platform
72-
if (platform === 'win32' && existsSync(join(pluginSettings.rootPath, 'node_modules', '.bin', 'jest.cmd'))) {
73-
return normalize(join(pluginSettings.rootPath, 'node_modules', '.bin', 'jest.cmd'))
74-
} else if (
75-
(platform === 'linux' || platform === 'darwin') &&
76-
existsSync(join(pluginSettings.rootPath, 'node_modules', '.bin', 'jest'))
77-
) {
78-
return normalize(join(pluginSettings.rootPath, 'node_modules', '.bin', 'jest'))
68+
if (isBootstrappedWithCreateReactApp(rootPath)) {
69+
return 'npm test --'
7970
}
8071

81-
return 'jest'
72+
const localJestExecutable = pathToLocalJestExecutable(rootPath)
73+
if (existsSync(localJestExecutable)) {
74+
return localJestExecutable
75+
}
76+
return `jest${isWindows() ? '.cmd' : ''}`
77+
}
78+
79+
function pathToLocalJestExecutable(rootDir) {
80+
return normalize(join(rootDir, `node_modules/.bin/jest${isWindows() ? '.cmd' : ''}`))
81+
}
82+
83+
function isWindows() {
84+
return platform() === 'win32'
8285
}
8386

8487
/**

tests/DebugConfigurationProvider.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
jest.unmock('../src/DebugConfigurationProvider')
22

33
import { DebugConfigurationProvider } from '../src/DebugConfigurationProvider'
4-
import { getTestCommand, isCRATestCommand } from '../src/helpers'
4+
import { getTestCommand, isCreateReactAppTestCommand } from '../src/helpers'
55

66
describe('DebugConfigurationProvider', () => {
77
it('should by default return a DebugConfiguration for Jest', () => {
@@ -18,7 +18,7 @@ describe('DebugConfigurationProvider', () => {
1818
})
1919
it('should return a valid CRA DebugConfiguration', () => {
2020
;(getTestCommand as jest.Mock<Function>).mockReturnValueOnce('react-scripts test --env=jsdom')
21-
;(isCRATestCommand as jest.Mock<Function>).mockReturnValueOnce(true)
21+
;(isCreateReactAppTestCommand as jest.Mock<Function>).mockReturnValueOnce(true)
2222

2323
const folder: any = { uri: { fsPath: null } }
2424
const sut = new DebugConfigurationProvider()

0 commit comments

Comments
 (0)