Skip to content

Commit

Permalink
test: Add tests for resolveTaskFn
Browse files Browse the repository at this point in the history
Move some tests from makeCmdTasks to resolveTaskFn.
  • Loading branch information
sudo-suhas committed May 5, 2018
1 parent 30559ed commit cde5d74
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 194 deletions.
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const debug = require('debug')('lint-staged')
// Force colors for packages that depend on https://www.npmjs.com/package/supports-color
// but do this only in TTY mode
if (process.stdout.isTTY) {
// istanbul ignore next
process.env.FORCE_COLOR = true
}

Expand Down
1 change: 1 addition & 0 deletions src/printErrors.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict'

// istanbul ignore next
// Work-around for duplicated error logs, see #142
const errMsg = err => (err.privateMsg != null ? err.privateMsg : err.message)

Expand Down
34 changes: 0 additions & 34 deletions test/makeCmdTasks-mock-findBin.spec.js

This file was deleted.

16 changes: 0 additions & 16 deletions test/makeCmdTasks-mock-isWindows.spec.js

This file was deleted.

52 changes: 0 additions & 52 deletions test/makeCmdTasks-mock-pMap.spec.js

This file was deleted.

98 changes: 6 additions & 92 deletions test/makeCmdTasks.spec.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
import dedent from 'dedent'
import mockFn from 'execa'
import logSymbols from 'log-symbols'
import execa from 'execa'
import makeCmdTasks from '../src/makeCmdTasks'
import resolveGitDir from '../src/resolveGitDir'

jest.mock('../src/resolveGitDir')

resolveGitDir.mockReturnValue(process.cwd())

describe('makeCmdTasks', () => {
beforeEach(() => {
resolveGitDir.mockClear()
mockFn.mockClear()
execa.mockClear()
})

it('should return an array', () => {
expect(makeCmdTasks('test', ['test.js'])).toBeInstanceOf(Array)
})

it('should throw for non-existent script', () => {
expect(() => {
makeCmdTasks('missing-module', ['test.js'])[0].task()
}).toThrow()
})

it('should work with a single command', async () => {
expect.assertions(4)
const res = makeCmdTasks('test', ['test.js'])
Expand All @@ -47,84 +33,12 @@ describe('makeCmdTasks', () => {
let taskPromise = linter1.task()
expect(taskPromise).toBeInstanceOf(Promise)
await taskPromise
expect(mockFn).toHaveBeenCalledTimes(1)
expect(mockFn).lastCalledWith('test', ['test.js'], { reject: false })
expect(execa).toHaveBeenCalledTimes(1)
expect(execa).lastCalledWith('test', ['test.js'], { reject: false })
taskPromise = linter2.task()
expect(taskPromise).toBeInstanceOf(Promise)
await taskPromise
expect(mockFn).toHaveBeenCalledTimes(2)
expect(mockFn).lastCalledWith('test2', ['test.js'], { reject: false })
})

it('should support non npm scripts', async () => {
expect.assertions(7)
const res = makeCmdTasks(['node --arg=true ./myscript.js', 'git add'], ['test.js'])
expect(res.length).toBe(2)
const [linter1, linter2] = res
expect(linter1.title).toBe('node --arg=true ./myscript.js')
expect(linter2.title).toBe('git add')

await linter1.task()
expect(mockFn).toHaveBeenCalledTimes(1)
expect(mockFn).lastCalledWith('node', ['--arg=true', './myscript.js', 'test.js'], {
reject: false
})

await linter2.task()
expect(mockFn).toHaveBeenCalledTimes(2)
expect(mockFn).lastCalledWith('git', ['add', 'test.js'], { reject: false })
})

it('should pass cwd to execa if gitDir is different than process.cwd for non-npm tasks', async () => {
expect.assertions(4)
resolveGitDir.mockReturnValueOnce('../')
const res = makeCmdTasks(['test', 'git add'], ['test.js'])
const [linter1, linter2] = res
await linter1.task()
expect(mockFn).toHaveBeenCalledTimes(1)
expect(mockFn).lastCalledWith('test', ['test.js'], { reject: false })

await linter2.task()
expect(mockFn).toHaveBeenCalledTimes(2)
expect(mockFn).lastCalledWith('git', ['add', 'test.js'], {
cwd: '../',
reject: false
})
})

it('should not pass `gitDir` as `cwd` to `execa()` if a non-git binary is called', async () => {
expect.assertions(2)
const processCwdBkp = process.cwd
process.cwd = () => __dirname
const [linter] = makeCmdTasks(['jest'], ['test.js'], { reject: false })
await linter.task()
expect(mockFn).toHaveBeenCalledTimes(1)
expect(mockFn).lastCalledWith('jest', ['test.js'], { reject: false })
process.cwd = processCwdBkp
})

it('should throw error for failed linters', async () => {
expect.assertions(1)
mockFn.mockImplementationOnce(() =>
Promise.resolve({
stdout: 'Mock error',
stderr: '',
code: 0,
failed: true,
cmd: 'mock cmd'
})
)

const [linter] = makeCmdTasks('mock-fail-linter', ['test.js'])
try {
await linter.task()
} catch (err) {
expect(err.privateMsg).toMatch(dedent`
${
logSymbols.error
} "mock-fail-linter" found some errors. Please fix them and try committing again.
Mock error
`)
}
expect(execa).toHaveBeenCalledTimes(2)
expect(execa).lastCalledWith('test2', ['test.js'], { reject: false })
})
})
127 changes: 127 additions & 0 deletions test/resolveTaskFn-chunked.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import dedent from 'dedent'
import execa from 'execa'
import isWindows from 'is-windows'
import logSymbols from 'log-symbols'
import pMap from 'p-map'
import resolveTaskFn from '../src/resolveTaskFn'

jest.mock('is-windows', () => jest.fn(() => true))
jest.mock('p-map')

const defaultOpts = {
linter: 'test',
pathsToLint: ['test.js'],
chunkSize: 1,
subTaskConcurrency: 1
}

describe('resolveTaskFn', () => {
describe('chunked tasks', () => {
afterEach(() => {
execa.mockClear()
pMap.mockClear()
})

pMap.mockResolvedValue([
{
stdout: 'a-ok',
stderr: '',
code: 0,
failed: false,
cmd: 'mock cmd'
}
])

it('should invoke execa in mapper function', async () => {
expect.assertions(3)

const taskFn = resolveTaskFn({ ...defaultOpts })
await taskFn()
const [[[chunk], mapper]] = pMap.mock.calls
expect(pMap).toHaveBeenCalledWith([['test.js']], mapper, { concurrency: 1 })
await mapper(chunk)
expect(execa).toHaveBeenCalledTimes(1)
expect(execa).toHaveBeenCalledWith('test', ['test.js'], { reject: false })
})

it('should respect chunk size and concurrency', async () => {
expect.assertions(6)

const taskFn = resolveTaskFn({
...defaultOpts,
pathsToLint: ['test1.js', 'test2.js'],
subTaskConcurrency: 2
})
await taskFn()
const [[chunks, mapper]] = pMap.mock.calls
expect(mapper).toBeInstanceOf(Function)
expect(pMap).toHaveBeenCalledWith([['test1.js'], ['test2.js']], mapper, { concurrency: 2 })

// Check that calling the mapper invokes execa
const [c1, c2] = chunks
await mapper(c1)
expect(execa).toHaveBeenCalledTimes(1)
expect(execa).lastCalledWith('test', ['test1.js'], { reject: false })
await mapper(c2)
expect(execa).toHaveBeenCalledTimes(2)
expect(execa).lastCalledWith('test', ['test2.js'], { reject: false })
})

it('should not return task fn with chunked execution if OS is not Windows', async () => {
expect.assertions(3)
isWindows.mockReturnValueOnce(false)

const taskFn = resolveTaskFn({
...defaultOpts,
pathsToLint: ['test1.js', 'test2.js']
})
await taskFn()
expect(pMap).not.toHaveBeenCalled()
expect(execa).toHaveBeenCalledTimes(1)
expect(execa).toHaveBeenCalledWith('test', ['test1.js', 'test2.js'], { reject: false })
})

it('should throw error for failed linters', async () => {
expect.assertions(1)
pMap.mockResolvedValueOnce([
{
stdout: 'Mock error',
stderr: '',
code: 0,
failed: true,
cmd: 'mock cmd'
}
])

const taskFn = resolveTaskFn({
...defaultOpts,
linter: 'mock-fail-linter'
})
try {
await taskFn()
} catch (err) {
expect(err.privateMsg).toMatch(dedent`
${
logSymbols.error
} "mock-fail-linter" found some errors. Please fix them and try committing again.
Mock error
`)
}
})

it('should handle unexpected error', async () => {
expect.assertions(1)
pMap.mockRejectedValueOnce(new Error('Unexpected Error'))

const taskFn = resolveTaskFn({ ...defaultOpts })
try {
await taskFn()
} catch (err) {
expect(err.message).toMatch(dedent`
${logSymbols.error} test got an unexpected error.
Unexpected Error
`)
}
})
})
})

0 comments on commit cde5d74

Please sign in to comment.