1
0
Fork 0

Add additional tests

pull/1562/head
Nikolai Laevskii 2023-10-12 09:21:26 +02:00
parent 1581d81aba
commit 0d75606364
2 changed files with 253 additions and 27 deletions

View File

@ -1,4 +1,5 @@
import * as exec from '@actions/exec'
import * as core from '@actions/core'
import {CommandRunner, createCommandRunner} from '../src/helpers'
describe('command-runner', () => {
@ -12,6 +13,7 @@ describe('command-runner', () => {
describe('CommandRunner', () => {
const execSpy = jest.spyOn(exec, 'exec')
const failSpy = jest.spyOn(core, 'setFailed')
afterEach(() => {
jest.resetAllMocks()
@ -199,6 +201,228 @@ describe('command-runner', () => {
expect(middleware).toHaveBeenCalledTimes(1)
})
it('fails if event matches', async () => {
execSpy.mockImplementation(
createExecMock({stdout: '', stderr: '', exitCode: 1})
)
failSpy.mockImplementation(() => {})
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.on('!stdout', 'fail')
.run()
expect(failSpy).toHaveBeenCalledWith(
`The command "echo" finished with exit code 1 and produced an empty output.`
)
})
it('throws error if event matches', async () => {
execSpy.mockImplementation(
createExecMock({stdout: '', stderr: '', exitCode: 1})
)
const cmdPromise = createCommandRunner('echo', ['hello', 'world'])
.onExitCode('> 0', 'throw')
.run()
await expect(cmdPromise).rejects.toThrow(
'The command "echo" finished with exit code 1 and produced an empty output.'
)
})
it('logs if event matches', async () => {
execSpy.mockImplementation(
createExecMock({stdout: '', stderr: 'test', exitCode: 1})
)
const logSpy = jest.spyOn(core, 'error')
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.on('!ok', 'log')
.run()
expect(logSpy).toHaveBeenCalledWith(
'The command "echo" finished with exit code 1 and produced an error: test'
)
})
})
describe('default handlers', () => {
test('onEmptyOutput', async () => {
execSpy.mockImplementation(
createExecMock({stdout: '', stderr: '', exitCode: 0})
)
const notCalledMiddleware = jest.fn()
const middleware = jest.fn()
await createCommandRunner('echo', ['hello', 'world'])
.onError(notCalledMiddleware)
.onEmptyOutput(middleware)
.onError(notCalledMiddleware)
.run()
expect(middleware).toHaveBeenCalledTimes(1)
expect(notCalledMiddleware).not.toHaveBeenCalled()
})
test('onExecutionError', async () => {
execSpy.mockImplementation(() => {
throw new Error('test')
})
const notCalledMiddleware = jest.fn()
const middleware = jest.fn()
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.onSuccess(notCalledMiddleware)
.onExecutionError(middleware)
.onSuccess(notCalledMiddleware)
.run()
expect(middleware).toHaveBeenCalledTimes(1)
expect(notCalledMiddleware).not.toHaveBeenCalled()
})
test('onStdError', async () => {
execSpy.mockImplementation(
createExecMock({stdout: '', stderr: 'test', exitCode: 0})
)
const notCalledMiddleware = jest.fn()
const middleware = jest.fn()
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.onSuccess(notCalledMiddleware)
.onStdError(middleware)
.onSuccess(notCalledMiddleware)
.run()
expect(middleware).toHaveBeenCalledTimes(1)
expect(notCalledMiddleware).not.toHaveBeenCalled()
})
test('onError', async () => {
execSpy.mockImplementation(
createExecMock({stdout: '', stderr: 'test', exitCode: 0})
)
const notCalledMiddleware = jest.fn()
const middleware = jest.fn()
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.onSuccess(notCalledMiddleware)
.onError(middleware)
.onSuccess(notCalledMiddleware)
.run()
execSpy.mockImplementation(() => {
throw new Error('test')
})
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.onSuccess(notCalledMiddleware)
.onError(middleware)
.onSuccess(notCalledMiddleware)
.run()
expect(middleware).toHaveBeenCalledTimes(2)
expect(notCalledMiddleware).not.toHaveBeenCalled()
})
test('onSpecificError', async () => {
execSpy.mockImplementation(
createExecMock({stdout: '', stderr: 'test', exitCode: 0})
)
const notCalledMiddleware = jest.fn()
const middleware = jest.fn()
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.onSuccess(notCalledMiddleware)
.onSpecificError(/test/, middleware)
.onSuccess(notCalledMiddleware)
.run()
expect(middleware).toHaveBeenCalledTimes(1)
expect(notCalledMiddleware).not.toHaveBeenCalled()
})
test('onSuccess', async () => {
execSpy.mockImplementation(
createExecMock({stdout: '', stderr: '', exitCode: 0})
)
const notCalledMiddleware = jest.fn()
const middleware = jest.fn()
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.onError(notCalledMiddleware)
.onSuccess(middleware)
.onError(notCalledMiddleware)
.run()
expect(middleware).toHaveBeenCalledTimes(1)
expect(notCalledMiddleware).not.toHaveBeenCalled()
})
test('onExitcode', async () => {
execSpy.mockImplementation(
createExecMock({stdout: '', stderr: '', exitCode: 2})
)
const notCalledMiddleware = jest.fn()
const middleware = jest.fn()
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.onSuccess(notCalledMiddleware)
.onExitCode('> 0', middleware)
.onSuccess(notCalledMiddleware)
.run()
expect(middleware).toHaveBeenCalledTimes(1)
expect(notCalledMiddleware).not.toHaveBeenCalled()
})
test('onOutput', async () => {
execSpy.mockImplementation(
createExecMock({stdout: 'test', stderr: '', exitCode: 0})
)
const notCalledMiddleware = jest.fn()
const middleware = jest.fn()
await createCommandRunner('echo', ['hello', 'world'], {
silent: true
})
.onError(notCalledMiddleware)
.onOutput(/test/, middleware)
.onError(notCalledMiddleware)
.run()
expect(middleware).toHaveBeenCalledTimes(1)
expect(notCalledMiddleware).not.toHaveBeenCalled()
})
})
})
})

View File

@ -92,36 +92,38 @@ export const failAction: CommandRunnerAction = message => async ctx => {
/**
* Throws an error with the given message or with a default one depending on execution conditions.
*/
export const throwError: CommandRunnerAction = message => async ctx => {
const events = getEventTypesFromContext(ctx)
export const throwError: CommandRunnerAction = message => {
return async ctx => {
const events = getEventTypesFromContext(ctx)
if (message !== undefined) {
throw new Error(
typeof message === 'string' ? message : message(ctx, events)
)
}
if (events.includes('execerr')) {
throw new Error(
`The command "${ctx.commandLine}" failed to run: ${ctx.execerr?.message}`
)
}
if (events.includes('stderr')) {
throw new Error(
`The command "${ctx.commandLine}" finished with exit code ${ctx.exitCode} and produced an error: ${ctx.stderr}`
)
}
if (!events.includes('stdout')) {
throw new Error(
`The command "${ctx.commandLine}" finished with exit code ${ctx.exitCode} and produced an empty output.`
)
}
if (message !== undefined) {
throw new Error(
typeof message === 'string' ? message : message(ctx, events)
`The command "${ctx.commandLine}" finished with exit code ${ctx.exitCode} and produced the following output: ${ctx.stdout}`
)
}
if (events.includes('execerr')) {
throw new Error(
`The command "${ctx.commandLine}" failed to run: ${ctx.execerr?.message}`
)
}
if (events.includes('stderr')) {
throw new Error(
`The command "${ctx.commandLine}" finished with exit code ${ctx.exitCode} and produced an error: ${ctx.stderr}`
)
}
if (!events.includes('stdout')) {
throw new Error(
`The command "${ctx.commandLine}" finished with exit code ${ctx.exitCode} and produced an empty output.`
)
}
throw new Error(
`The command "${ctx.commandLine}" finished with exit code ${ctx.exitCode} and produced the following output: ${ctx.stdout}`
)
}
/**
@ -345,7 +347,7 @@ export const matchExitCode = (
return async (ctx, next) => {
// if exit code is undefined, NaN will not match anything
if (matcherFn(ctx.exitCode ?? NaN)) {
composedMiddleware(ctx, next)
await composedMiddleware(ctx, next)
return
}