Skip to content

Commit

Permalink
New: Create a new config file if one doesn't exist
Browse files Browse the repository at this point in the history
Fix #354
Close #429
  • Loading branch information
qczhou authored and alrra committed Aug 19, 2017
1 parent e9e4a95 commit d515c5a
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 5 deletions.
51 changes: 46 additions & 5 deletions src/lib/cli.ts
Expand Up @@ -18,6 +18,7 @@ import * as path from 'path';
import * as chalk from 'chalk';
import * as ora from 'ora';
import * as updateNotifier from 'update-notifier';
import * as inquirer from 'inquirer';

import * as Config from './config';
import { debug as d } from './utils/debug';
Expand Down Expand Up @@ -79,6 +80,41 @@ const notifyNewVersion = (update: updateNotifier.UpdateInfo) => {
notifier.notify({ message });
};

const confirmLaunchInit = () => {
debug(`Initiating launch init confirm.`);

const question: Array<object> = [{
message: `A valid configuration file can't be found. Do you want to create a new one?`,
name: 'confirm',
type: 'confirm'
}];

return inquirer.prompt(question);
};

const loadOrCreateIfNotExits = async () => {
let config: IConfig;
let configPath: string;

try {
configPath = Config.getFilenameForDirectory(process.cwd());
debug(`Loading configuration file from ${configPath}.`);
config = Config.load(configPath);
} catch (err) {
// The config file doesn't exist, launch `init` if user permits.
const launchInit: { confirm: boolean } = await confirmLaunchInit();

if (launchInit.confirm) {
await initSonarrc();
logger.log(`Configuration file .sonarrc was created.`);

return loadOrCreateIfNotExits();
}
}

return config;
};

// ------------------------------------------------------------------------------
// Public
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -135,15 +171,20 @@ export const execute = async (args: string | Array<string> | Object): Promise<nu
return 0;
}

let configPath: string;
let config: IConfig;
const configPathFromInput: string = currentOptions.config;

if (!currentOptions.config) {
configPath = Config.getFilenameForDirectory(process.cwd());
if (configPathFromInput) {
config = Config.load(configPathFromInput);
} else {
configPath = currentOptions.config;
config = await loadOrCreateIfNotExits();
}

const config: IConfig = Config.load(configPath);
if (!config) {
logger.log(`Unable to find a valid configuration file. Please add a .sonarrc file by running 'sonar --init'. `);

return 1;
}

sonar = new Sonar(config);
const start: number = Date.now();
Expand Down
45 changes: 45 additions & 0 deletions tests/lib/cli.ts
Expand Up @@ -45,12 +45,15 @@ const updateNotifier = () => {
return stubbedNotifier;
};

const inquirer = { prompt() { } };

proxyquire('../../src/lib/cli', {
'./cli/sonarrc-generator': generator,
'./config': config,
'./sonar': { Sonar },
'./utils/logging': logger,
'./utils/resource-loader': resourceLoader,
inquirer,
ora,
'update-notifier': updateNotifier
});
Expand All @@ -68,12 +71,14 @@ test.beforeEach((t) => {
sinon.spy(spinner, 'start');
sinon.spy(spinner, 'fail');
sinon.spy(spinner, 'succeed');
sinon.spy(inquirer, 'prompt');

t.context.config = config;
t.context.generator = generator;
t.context.logger = logger;
t.context.spinner = spinner;
t.context.notifier = stubbedNotifier;
t.context.inquirer = inquirer;
});

test.afterEach.always((t) => {
Expand All @@ -86,6 +91,7 @@ test.afterEach.always((t) => {
t.context.spinner.fail.restore();
t.context.spinner.succeed.restore();
t.context.notifier.notify.restore();
t.context.inquirer.prompt.restore();
});

test.serial('if version option is defined, it should print the current version and return with exit code 0', async (t) => {
Expand Down Expand Up @@ -117,6 +123,45 @@ test.serial('if config is not defined, it should get the config file from the di
t.true(t.context.config.getFilenameForDirectory.called);
});

test.serial('If config file does not exist, it should create a configuration file if user agrees', async (t) => {
const error = { message: `Couldn't find any valid configuration` };

t.context.config.load.restore();
t.context.inquirer.prompt.restore();

sinon.stub(t.context.config, 'load')
.onFirstCall()
.throws(error)
.onSecondCall()
.returns({});
sinon.stub(inquirer, 'prompt').resolves({ confirm: true });

await cli.execute('http://localhost/');

t.true(t.context.inquirer.prompt.calledOnce);
t.is(t.context.inquirer.prompt.args[0][0][0].name, 'confirm');
t.true(t.context.generator.initSonarrc.calledOnce);
});

test.serial('If config file does not exist and user refuses to create a configuration file, it should exit with code 1', async (t) => {
const error = { message: `Couldn't find any valid configuration` };

t.context.config.load.restore();
t.context.inquirer.prompt.restore();

sinon.stub(t.context.config, 'load')
.onFirstCall()
.throws(error);
sinon.stub(inquirer, 'prompt').resolves({ confirm: false });

const exitCode = await cli.execute('http://localhost/');

t.true(t.context.inquirer.prompt.calledOnce);
t.is(t.context.inquirer.prompt.args[0][0][0].name, 'confirm');
t.false(t.context.generator.initSonarrc.called);
t.is(exitCode, 1);
});

test.serial('if configuration file exists, it should use it', async (t) => {
t.context.config.load.restore();
sinon.stub(t.context.config, 'load').returns({});
Expand Down

0 comments on commit d515c5a

Please sign in to comment.