Skip to content

Commit cca25cc

Browse files
committed
Merge pull request jest-community#1 from stephtr/feature/improve-jest-detection
Extract `nodeBinExtension` as variable
2 parents 2a9e7ca + 3a0e5a5 commit cca25cc

2 files changed

Lines changed: 59 additions & 58 deletions

File tree

src/helpers.ts

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,26 @@ import { IPluginResourceSettings, hasUserSetPathToJest } from './Settings'
99
*/
1010
const createReactAppBinaryNames = ['react-scripts', 'react-native-scripts', 'react-scripts-ts', 'react-app-rewired']
1111

12+
/**
13+
* File extension for npm binaries
14+
*/
15+
export const nodeBinExtension: string = platform() === 'win32' ? '.cmd' : ''
16+
17+
/**
18+
* Resolves the location of an npm binary
19+
*/
20+
function getLocalPathForExecutable(rootPath: string, executable: string): string {
21+
return normalize(join(rootPath, 'node_modules', '.bin', executable + nodeBinExtension))
22+
}
23+
24+
/**
25+
* Checks whether an npm binary exists
26+
*/
27+
function hasNodeExecutable(rootPath: string, executable: string): boolean {
28+
const absolutePath = getLocalPathForExecutable(rootPath, executable)
29+
return existsSync(absolutePath)
30+
}
31+
1232
/**
1333
* Tries to read the test command from the scripts section within `package.json`
1434
*
@@ -49,21 +69,6 @@ function isBootstrappedWithCreateReactApp(rootPath: string): boolean {
4969
return isCreateReactAppTestCommand(testCommand)
5070
}
5171

52-
function getPlatformJestExecutable(executable: string): string {
53-
const ext = platform() === 'win32' ? '.cmd' : ''
54-
return executable + ext
55-
}
56-
57-
function getLocalPathForExecutable(rootPath: string, executable: string): string {
58-
const platformExecutable = getPlatformJestExecutable(executable)
59-
return normalize(join(rootPath, 'node_modules', '.bin', platformExecutable))
60-
}
61-
62-
function hasNodeExecutable(rootPath: string, executable: string): boolean {
63-
const absolutePath = getLocalPathForExecutable(rootPath, executable)
64-
return existsSync(absolutePath)
65-
}
66-
6772
/**
6873
* Handles getting the jest runner, handling the OS and project specific work too
6974
*
@@ -84,7 +89,7 @@ export function pathToJest({ pathToJest, rootPath }: IPluginResourceSettings) {
8489
return localJestExecutable
8590
}
8691

87-
return getPlatformJestExecutable('jest')
92+
return 'jest' + nodeBinExtension
8893
}
8994

9095
/**
@@ -124,7 +129,7 @@ export function pathToJestPackageJSON(pluginSettings: IPluginResourceSettings):
124129
return null
125130
}
126131

127-
function removeSurroundingQuotes(str) {
132+
function removeSurroundingQuotes(str: string) {
128133
return str.replace(/^['"`]/, '').replace(/['"`]$/, '')
129134
}
130135

tests/helpers.test.ts

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,28 @@ jest.mock('path', () => ({
1818
normalize: mockNormalize,
1919
}))
2020

21-
import { isCreateReactAppTestCommand, pathToJest, pathToJestPackageJSON } from '../src/helpers'
21+
import { isCreateReactAppTestCommand, pathToJest, pathToJestPackageJSON, nodeBinExtension } from '../src/helpers'
2222
import * as path from 'path'
2323

24+
// Manually (forcefully) set the executable's file extension to test its addition independendly of the operating system.
25+
;(nodeBinExtension as string) = '.TEST'
26+
2427
describe('ModuleHelpers', () => {
28+
describe('nodeBinExtension', () => {
29+
// Since `nodeBinExtension` is a variable, we have to reload the module in order to re-evaluate it.
30+
it('should return an empty string on Linux', () => {
31+
jest.resetModules()
32+
mockPlatform.mockReturnValueOnce('linux')
33+
expect(require('../src/helpers').nodeBinExtension).toBe('')
34+
})
35+
36+
it('should equal ".cmd" on Windows', () => {
37+
jest.resetModules()
38+
mockPlatform.mockReturnValueOnce('win32')
39+
expect(require('../src/helpers').nodeBinExtension).toBe('.cmd')
40+
})
41+
})
42+
2543
describe('pathToJestPackageJSON', () => {
2644
const defaultPathToJest = null
2745
const defaultSettings: any = {
@@ -145,6 +163,12 @@ describe('ModuleHelpers', () => {
145163
rootPath: '',
146164
}
147165

166+
beforeEach(() => {
167+
mockJoin.mockImplementation(require.requireActual('path').join)
168+
mockNormalize.mockImplementation(require.requireActual('path').normalize)
169+
mockExistsSync.mockImplementation(require.requireActual('path').existsSync)
170+
})
171+
148172
it('returns "npm test --" when bootstrapped with create-react-app', () => {
149173
mockReadFileSync.mockReturnValueOnce(
150174
JSON.stringify({
@@ -170,52 +194,24 @@ describe('ModuleHelpers', () => {
170194
expect(mockNormalize).toBeCalledWith(settings.pathToJest)
171195
})
172196

173-
describe('os platform: linux', () => {
174-
it('defaults to "node_modules/.bin/jest" when Jest is locally installed', () => {
175-
const expected = 'node_modules/.bin/jest'
197+
it('defaults to "node_modules/.bin/jest" when Jest is locally installed', () => {
198+
const expected = 'node_modules/.bin/jest.TEST'
176199

177-
mockJoin.mockImplementation(require.requireActual('path').posix.join)
178-
mockPlatform.mockReturnValue('linux')
179-
mockNormalize.mockImplementationOnce(arg => arg)
180-
mockExistsSync.mockImplementation(path => path === expected)
200+
mockJoin.mockImplementation(require.requireActual('path').posix.join)
201+
mockNormalize.mockImplementation(arg => arg)
202+
mockExistsSync.mockImplementation(path => path === expected)
181203

182-
expect(pathToJest(defaultSettings)).toBe(expected)
183-
})
184-
185-
it('defaults to "jest" when Jest is locally installed', () => {
186-
const expected = 'jest'
187-
188-
mockJoin.mockImplementation(require.requireActual('path').posix.join)
189-
mockPlatform.mockReturnValue('linux')
190-
mockNormalize.mockImplementationOnce(arg => arg)
191-
mockExistsSync.mockImplementation(_ => false)
192-
193-
expect(pathToJest(defaultSettings)).toBe(expected)
194-
})
204+
expect(pathToJest(defaultSettings)).toBe(expected)
195205
})
196206

197-
describe('os platform: win32', () => {
198-
it('defaults to "node_modules/.bin/jest.cmd" when Jest is locally installed', () => {
199-
const expected = 'node_modules/.bin/jest.cmd'
207+
it('defaults to "jest" when Jest is not locally installed', () => {
208+
const expected = 'jest.TEST'
200209

201-
mockJoin.mockImplementation(require.requireActual('path').posix.join)
202-
mockPlatform.mockReturnValue('win32')
203-
mockNormalize.mockImplementationOnce(arg => arg)
204-
mockExistsSync.mockImplementation(path => path === expected)
210+
mockJoin.mockImplementation(require.requireActual('path').posix.join)
211+
mockNormalize.mockImplementation(arg => arg)
212+
mockExistsSync.mockImplementation(_ => false)
205213

206-
expect(pathToJest(defaultSettings)).toBe(expected)
207-
})
208-
209-
it('defaults to "jest.cmd" when Jest is locally installed', () => {
210-
const expected = 'jest.cmd'
211-
212-
mockJoin.mockImplementation(require.requireActual('path').posix.join)
213-
mockPlatform.mockReturnValue('win32')
214-
mockNormalize.mockImplementationOnce(arg => arg)
215-
mockExistsSync.mockImplementation(_ => false)
216-
217-
expect(pathToJest(defaultSettings)).toBe(expected)
218-
})
214+
expect(pathToJest(defaultSettings)).toBe(expected)
219215
})
220216
})
221217
})

0 commit comments

Comments
 (0)