Skip to content

Commit

Permalink
test: improve test coverage
Browse files Browse the repository at this point in the history
Signed-off-by: Lenin Mehedy <[email protected]>
  • Loading branch information
leninmehedy committed Feb 28, 2024
1 parent f739ada commit 2ccc09f
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 29 deletions.
19 changes: 3 additions & 16 deletions src/commands/base.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,7 @@
import { FullstackTestingError, MissingArgumentError } from '../core/errors.mjs'
import { ConfigManager } from '../core/index.mjs'
import { ShellRunner } from '../core/shell_runner.mjs'

/**
* This is a default command error handler used by handleCommand
* @param err error
* @param logger logger
*/
const defaultErrorHandler = (err, logger) => {
logger.showUserError(err)

// do not exit immediately so that logger can flush properly
setTimeout(() => {
process.exit(1)
}, 1)
}
import * as helpers from '../core/helpers.mjs'

export class BaseCommand extends ShellRunner {
async prepareChartPath (chartDir, chartRepo, chartName) {
Expand Down Expand Up @@ -74,14 +61,14 @@ export class BaseCommand extends ShellRunner {
* @param errHandler error handler
* @return {Promise<void>}
*/
async handleCommand (argv, handleFunc, errHandler = defaultErrorHandler) {
async handleCommand (argv, handleFunc, errHandler = helpers.defaultErrorHandler) {
if (!argv) throw new MissingArgumentError('argv is required')
if (!handleFunc) throw new MissingArgumentError('handleFunc is required')

let error = null
try {
this.logger.debug(`==== Start: '${argv._.join(' ')}' ===`, { config: this.configManager.config, argv })
await ConfigManager.acquireProcessLock(this.logger)
await ConfigManager.acquireProcessLock(this.logger, errHandler)
await handleFunc(argv)
} catch (e) {
error = new FullstackTestingError(`Error occurred: ${e.message}`, e)

Check warning on line 74 in src/commands/base.mjs

View check run for this annotation

Codecov / codecov/patch

src/commands/base.mjs#L74

Added line #L74 was not covered by tests
Expand Down
3 changes: 1 addition & 2 deletions src/commands/init.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ export class InitCommand extends BaseCommand {
},
handler: argv => initCmd.handleCommand(

Check warning on line 166 in src/commands/init.mjs

View check run for this annotation

Codecov / codecov/patch

src/commands/init.mjs#L166

Added line #L166 was not covered by tests
argv,
async (args) => await initCmd.init(args),
initCmd.logger
async (args) => await initCmd.init(args)

Check warning on line 168 in src/commands/init.mjs

View check run for this annotation

Codecov / codecov/patch

src/commands/init.mjs#L168

Added line #L168 was not covered by tests
)
}
}
Expand Down
11 changes: 5 additions & 6 deletions src/core/config_manager.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export class ConfigManager {
* @param lockExistHandler error handler when lock exists
* @return {void}
*/
static acquireProcessLock (logger, lockExistHandler = (existingPid) => { process.exit(1) }) {
static async acquireProcessLock (logger, lockExistHandler = helpers.defaultErrorHandler) {
const pid = process.pid.toString()
const pidFile = path.normalize(constants.SOLO_PID_FILE)
if (!fs.existsSync(pidFile)) {
Expand All @@ -254,10 +254,9 @@ export class ConfigManager {

// pid lock exists
const existingPid = fs.readFileSync(pidFile).toString()
logger.showUserError(new FullstackTestingError(`Process lock exists: ${constants.SOLO_PID_FILE}` +
`\nEnsure process '${existingPid}' is not running [ ps -p ${existingPid} ]`))

return lockExistHandler(existingPid)
const err = new FullstackTestingError(`Process lock exists: ${constants.SOLO_PID_FILE}` +
`\nEnsure process '${existingPid}' is not running [ ps -p ${existingPid} ]`)
return lockExistHandler(err, logger)
}

/**
Expand All @@ -269,7 +268,7 @@ export class ConfigManager {
* @param logger
* @return {Promise<void>}
*/
static releaseProcessLock (logger) {
static async releaseProcessLock (logger) {
const pidFile = path.normalize(constants.SOLO_PID_FILE)
if (fs.existsSync(pidFile)) {
const existingPid = fs.readFileSync(pidFile).toString()
Expand Down
14 changes: 14 additions & 0 deletions src/core/helpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,17 @@ export function getRootImageRepository (releaseTag) {
export function getTmpDir () {
return fs.mkdtempSync(path.join(constants.SOLO_TMP_DIR, 'solo-'))
}

/**
* This is a default command error handler used by handleCommand
* @param err error
* @param logger logger
*/
export function defaultErrorHandler (err, logger) {
logger.showUserError(err)

Check warning on line 148 in src/core/helpers.mjs

View check run for this annotation

Codecov / codecov/patch

src/core/helpers.mjs#L147-L148

Added lines #L147 - L148 were not covered by tests

// do not exit immediately so that logger can flush properly
setTimeout(() => {
process.exit(1)

Check warning on line 152 in src/core/helpers.mjs

View check run for this annotation

Codecov / codecov/patch

src/core/helpers.mjs#L151-L152

Added lines #L151 - L152 were not covered by tests
}, 1)
}
36 changes: 36 additions & 0 deletions test/unit/commands/base.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
*
*/
import { expect, it, describe } from '@jest/globals'
import fs from 'fs'
import {
constants,
DependencyManager,
ChartManager,
ConfigManager,
Expand Down Expand Up @@ -51,4 +53,38 @@ describe('BaseCommand', () => {
await expect(baseCmd.run('date')).resolves.not.toBeNull()
})
})

describe('handle command', () => {
it('should succeed in running a valid command handler', async () => {
expect.assertions(2)
expect(fs.existsSync(constants.SOLO_PID_FILE)).toBeFalsy()

Check warning on line 60 in test/unit/commands/base.test.mjs

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

test/unit/commands/base.test.mjs#L60

The application dynamically constructs file or path information.

const argv = {}
argv._ = ['test']

let error = null
await baseCmd.handleCommand(argv,
async () => {
},
(err, logger) => {
error = err
}
)
expect(error).toBeNull()
})

it('should throw error if it fails to do process lock', async () => {
expect.assertions(2)
expect(fs.existsSync(constants.SOLO_PID_FILE)).toBeFalsy()
await ConfigManager.acquireProcessLock(testLogger)

const argv = {}
argv._ = ['test']
await baseCmd.handleCommand(argv, async () => {
}, (err, logger) => {
expect(err.message.startsWith('Process lock exists')).toBeTruthy()
})
await ConfigManager.releaseProcessLock(testLogger)
})
})
})
12 changes: 7 additions & 5 deletions test/unit/core/config_manager.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,17 @@ describe('ConfigManager', () => {
})

describe('process lock', () => {
it('should be able to acquire process lock', () => {
it('should be able to acquire process lock', async () => {
expect(fs.existsSync(constants.SOLO_PID_FILE)).toBeFalsy()
ConfigManager.acquireProcessLock(testLogger)
await ConfigManager.acquireProcessLock(testLogger)
expect(fs.existsSync(constants.SOLO_PID_FILE)).toBeTruthy()
expect(fs.readFileSync(constants.SOLO_PID_FILE).toString()).toStrictEqual(process.pid.toString())
ConfigManager.acquireProcessLock(testLogger, (existingPid) => {
expect(existingPid).toStrictEqual(process.pid.toString())

// re-attempt should fail
await ConfigManager.acquireProcessLock(testLogger, (err, _) => {
expect(err.message.startsWith('Process lock exists'))
})
ConfigManager.releaseProcessLock(testLogger)
await ConfigManager.releaseProcessLock(testLogger)
expect(fs.existsSync(constants.SOLO_PID_FILE)).toBeFalsy()
})
})
Expand Down

0 comments on commit 2ccc09f

Please sign in to comment.