Skip to content

Commit

Permalink
fix(test): begin covering main
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed Aug 28, 2020
1 parent 5870e66 commit 9364266
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 45 deletions.
99 changes: 56 additions & 43 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { doesExist, InvalidArgumentError } from '@apextoaster/js-utils';
import { Container } from 'noicejs';
import { Container, Logger } from 'noicejs';
import { alea } from 'seedrandom';

import { initConfig } from './config';
import { Commands, createParser } from './config/args';
import { initConfig, ProjectConfig } from './config';
import { Commands, createParser, ParsedArgs } from './config/args';
import { dotGraph, graphProject } from './graph';
import { BunyanLogger } from './logger/bunyan';
import { RemoteModule } from './module/RemoteModule';
Expand All @@ -19,12 +19,15 @@ export { GitlabRemote } from './remote/gitlab';
export { resolveLabels } from './resolve';
export { syncIssueLabels, syncProjectLabels } from './sync';

const SLICE_ARGS = 2;
const ARGS_START = 2;

export const STATUS_FAILURE = 1;
export const STATUS_SUCCESS = 0;

export async function main(argv: Array<string>): Promise<number> {
let mode = Commands.UNKNOWN as Commands;
const parser = createParser((argMode) => mode = argMode as Commands);
const args = parser.parse(argv.slice(SLICE_ARGS));
const args = parser.parse(argv.slice(ARGS_START));
const config = await initConfig(args.config);
const logger = BunyanLogger.create(config.logger);

Expand All @@ -41,48 +44,58 @@ export async function main(argv: Array<string>): Promise<number> {
await container.configure();

for (const project of config.projects) {
const { name } = project;

if (doesExist(args.project) && !args.project.includes(name)) {
logger.info({ project: name }, 'skipping project');
continue;
const projectStatus = await mainProject(args, container, logger, mode, project);
if (projectStatus !== STATUS_SUCCESS) {
return projectStatus;
}
}

const remote = await container.create<Remote, RemoteOptions>(project.remote.type, {
data: project.remote.data,
dryrun: defaultUntil(args.dryrun, project.remote.dryrun, false),
logger,
type: project.remote.type,
});
return STATUS_SUCCESS;
}

const connected = await remote.connect();
if (!connected) {
logger.error({ type: project.remote.type }, 'unable to connect to remote');
return 1;
}
/* eslint-disable-next-line max-params */
export async function mainProject(args: ParsedArgs, container: Container, logger: Logger, mode: Commands, project: ProjectConfig): Promise<number> {
const { name } = project;

// mode switch
const options: SyncOptions = {
logger,
project,
random: alea(name),
remote,
};
switch (mode) {
case Commands.GRAPH:
const graph = graphProject(project);
process.stdout.write(dotGraph(graph));
break;
case Commands.ISSUES:
await syncIssueLabels(options);
break;
case Commands.LABELS:
await syncProjectLabels(options);
break;
default:
throw new InvalidArgumentError('unknown command');
}
if (doesExist(args.project) && !args.project.includes(name)) {
logger.info({ project: name }, 'skipping project');
return STATUS_SUCCESS;
}

const remote = await container.create<Remote, RemoteOptions>(project.remote.type, {
data: project.remote.data,
dryrun: defaultUntil(args.dryrun, project.remote.dryrun, false),
logger,
type: project.remote.type,
});

const connected = await remote.connect();
if (!connected) {
logger.error({ type: project.remote.type }, 'unable to connect to remote');
return STATUS_FAILURE;
}

// mode switch
const options: SyncOptions = {
logger,
project,
random: alea(name),
remote,
};
switch (mode) {
case Commands.GRAPH:
const graph = graphProject(project);
process.stdout.write(dotGraph(graph));
break;
case Commands.ISSUES:
await syncIssueLabels(options);
break;
case Commands.LABELS:
await syncProjectLabels(options);
break;
default:
throw new InvalidArgumentError('unknown command');
}

return 0;
return STATUS_SUCCESS;
}
117 changes: 115 additions & 2 deletions test/TestMain.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,119 @@
import { NotImplementedError } from '@apextoaster/js-utils';
import { expect } from 'chai';
import { Container, NullLogger } from 'noicejs';
import { createStubInstance } from 'sinon';

import { Commands, ParsedArgs } from '../src/config/args';
import { GithubRemote, mainProject, Remote, RemoteOptions, STATUS_FAILURE, STATUS_SUCCESS } from '../src/main';
import { RemoteModule } from '../src/module/RemoteModule';

const TEST_REMOTE = 'test-remote';

describe('main app', () => {
it('should parse command line arguments');
it('should load config from file');
it('should create a remote');
it('should fail on errors');

it('should create a remote', async () => {
const args: ParsedArgs = {
config: '',
dryrun: true,
};
const logger = NullLogger.global;
const mode = Commands.GRAPH;

const remote = createStubInstance(GithubRemote);
remote.connect.returns(Promise.resolve(true));

const module = new RemoteModule();
module.bind<Remote, Remote, RemoteOptions>(TEST_REMOTE).toInstance(remote);

const container = Container.from(module);
await container.configure();

const status = await mainProject(args, container, logger, mode, {
colors: [],
comment: false,
flags: [],
name: '',
remote: {
data: {},
dryrun: true,
logger,
type: TEST_REMOTE,
},
states: [],
});

expect(status).to.equal(STATUS_SUCCESS);
});

it('should report connection failures', async () => {
const args: ParsedArgs = {
config: '',
dryrun: true,
};
const logger = NullLogger.global;
const mode = Commands.GRAPH;

const remote = createStubInstance(GithubRemote);
remote.connect.returns(Promise.resolve(false));

const module = new RemoteModule();
module.bind<Remote, Remote, RemoteOptions>(TEST_REMOTE).toInstance(remote);

const container = Container.from(module);
await container.configure();

const status = await mainProject(args, container, logger, mode, {
colors: [],
comment: false,
flags: [],
name: '',
remote: {
data: {},
dryrun: true,
logger,
type: TEST_REMOTE,
},
states: [],
});

expect(status).to.equal(STATUS_FAILURE);
});

it('should not connect to skipped projects', async () => {
const args: ParsedArgs = {
config: '',
dryrun: true,
project: ['foo']
};
const logger = NullLogger.global;
const mode = Commands.GRAPH;

const remote = createStubInstance(GithubRemote);
remote.connect.throws(new NotImplementedError());

const module = new RemoteModule();
module.bind<Remote, Remote, RemoteOptions>(TEST_REMOTE).toInstance(remote);

const container = Container.from(module);
await container.configure();

const status = await mainProject(args, container, logger, mode, {
colors: [],
comment: false,
flags: [],
name: 'bar',
remote: {
data: {},
dryrun: true,
logger,
type: TEST_REMOTE,
},
states: [],
});

expect(status).to.equal(STATUS_SUCCESS);
expect(remote.connect).to.have.callCount(0);
});
});

0 comments on commit 9364266

Please sign in to comment.