Skip to content

Commit

Permalink
Added more tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim Buck committed Aug 30, 2016
1 parent a5ddf70 commit 66c715e
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 48 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"exclude": [
"dist/**/*.spec.js",
"dist/**/*.d.ts",
"dist/*.js",
"coverage/**",
"node_modules/**"
]
Expand Down
5 changes: 2 additions & 3 deletions src/bin/pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const chalk = require('chalk');
const ansiEscapes = require('ansi-escapes');

import {Playbook, Project, Play} from '../';
import {first} from '../services/utils';
import {ProcessManager} from '../services/process-manager';

interface Answers {
Expand Down Expand Up @@ -196,7 +195,7 @@ function selectPlay(args: ParsedArgs): Promise<Play> {
}
]).then((answers: Answers): Promise<Play> => {
playName = <string>answers[answerName];
let play = first(plays, p => p.name === playName);
let play = plays.find(p => p.name === playName);
if (play) {
return Promise.resolve(play);
} else {
Expand Down Expand Up @@ -257,7 +256,7 @@ function deletePlay(play: Play): Promise<void>{
}

function runPlay(play: Play): Promise<void> {
procManager = play.run();
procManager = new ProcessManager(play.run());

return procManager.render((text) => {
app.ui.redraw(text);
Expand Down
2 changes: 1 addition & 1 deletion src/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ let pb = new Playbook();
let procManager: ProcessManager;

pb.get('main-app').then(play => {
procManager = play.run();
procManager = new ProcessManager(play.run());

return procManager.render((text) => {
process.stdout.write('\x1B[2J\x1B[0f');
Expand Down
114 changes: 114 additions & 0 deletions src/models/play.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import {resolve} from 'path';
import {ChildProcess, ExecOptions} from 'child_process';
import * as child_process from 'child_process';

import {test} from 'ava';
import {Play, IPlay} from './play';
import {Project, IProject} from './project';

test(`'Play' is a thing`, t => {
t.is(typeof Play, 'function');
});

test(`'Play' options are required`, t => {
t.throws(() => new Play(null));
});

test(`'Play' option 'name' is required`, t => {
t.throws(() => new Play({
name: null
}));
});

test(`'Play' options auto-populate 'projects' property`, t => {
let expected: IPlay = {
name: 'Next Best Thing',
projects: null
};
let play = new Play(expected);
t.not(typeof play, 'undefined');
t.true(Array.isArray(play.projects));
t.is(play.projects.length, 0);
});

test(`'Play' options convert 'project-like' to 'Project'`, t => {
let expected: IPlay = {
name: 'Next Best Thing',
projects: [{
name: 'One Fish',
cwd: '/two/fish',
command: 'red-fish',
args: ['blue', 'fish']
}]
};
let play = new Play(expected);
t.not(typeof play, 'undefined');
t.true(Array.isArray(play.projects));
t.is(play.projects.length, 1);
t.true(play.projects[0] instanceof Project);
});

test(`'Play' options populate values`, t => {
let expected: IPlay = {
name: 'Ava Tests Project',
cwd: '/some/test/directory'
};
let proj = new Play(expected);
t.not(typeof proj, 'undefined');
t.is(proj.name, expected.name);
t.is(proj.cwd, expected.cwd);
});

test(`'run' executes each project`, t => {
let origExec = child_process.exec;

let expectedProj: IProject = {
name: 'One Fish',
cwd: '/two/fish',
command: 'red-fish',
args: ['blue', 'fish']
};

let expected: IPlay = {
name: 'Next Best Thing',
cwd: '/some/test/location',
projects: [expectedProj]
};

child_process.exec = (command: string, args: ExecOptions): ChildProcess => {
t.is(command, `${expectedProj.command} ${expectedProj.args.join(' ')}`);
t.is(args.cwd, expectedProj.cwd);
return null;
}

let play = new Play(expected);

let result = play.run();

t.is(result.length, 1);
t.true(result[0] instanceof Project);
t.is(result[0].currentProcess, null);

child_process.exec = origExec;
});

test(`Play 'toString' returns the name and project count`, t => {
let expected: IPlay = {
name: 'Next Best Thing',
projects: [{
name: 'One Fish',
cwd: '/two/fish',
command: 'red-fish',
args: ['blue', 'fish']
}, {
name: 'Sam',
cwd: '/i/am',
command: 'green',
args: ['eggs', 'ham']
}]
};
let play = new Play(expected);
let result = play.toString();
t.is(typeof result, 'string');
t.is(result, `${play.name} (${play.projects.length})`);
})
16 changes: 6 additions & 10 deletions src/models/play.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
import {ChildProcess, exec} from 'child_process';

import {IProject, Project} from './project';
import {ProcessManager} from '../services/process-manager';

export interface IPlay
{
name: string;
cwd: string;
projects?: Project[];
cwd?: string;
projects?: IProject[];
}

export class Play implements IPlay
export class Play
{
public name: string;

Expand All @@ -20,7 +19,7 @@ export class Play implements IPlay
public projects: Project[];

constructor(data: IPlay) {
if (!data.name || data.name.length === 0) {
if (!data || !data.name || data.name.length === 0) {
throw new Error(`'name' is required!`);
}

Expand All @@ -29,16 +28,13 @@ export class Play implements IPlay
this.projects = (data.projects || []).map(proj => new Project(proj));
}

public run(): ProcessManager
public run(): Project[]
{
let projs = this.projects.map(proj => {
return this.projects.map(proj => {
proj.currentProcess = exec(`${proj.command} ${proj.args.join(' ')}`, { cwd: proj.cwd });
return proj;
});

return new ProcessManager(projs);
}


/**
* Prints out the name and count of projects.
Expand Down
45 changes: 45 additions & 0 deletions src/models/project.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {resolve} from 'path';

import {test} from 'ava';
import {Project, IProject} from './project';

test(`'Project' is a thing`, t => {
t.is(typeof Project, 'function');
});

test(`'Project' options are optional`, t => {
let proj = new Project();
t.not(typeof proj, 'undefined');
});

test(`'Project' options may be null`, t => {
let proj = new Project(null);
t.not(typeof proj, 'undefined');
});

test(`'Project' options auto-populate arguments property`, t => {
let expected: IProject = {
name: 'Ava Tests Project'
};
let proj = new Project(expected);
t.not(typeof proj, 'undefined');
t.true(Array.isArray(proj.args));
t.is(proj.args.length, 0);
});

test(`'Project' options populate values`, t => {
let expected: IProject = {
name: 'Ava Tests Project',
cwd: '/some/test/directory',
command: 'some-command',
args: ['1', '2', 'false'],
currentProcess: null
};
let proj = new Project(expected);
t.not(typeof proj, 'undefined');
t.is(proj.name, expected.name);
t.is(proj.cwd, expected.cwd);
t.is(proj.command, expected.command);
t.is(proj.args, expected.args);
t.is(proj.currentProcess, expected.currentProcess);
});
7 changes: 4 additions & 3 deletions src/services/process-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,14 @@ class StatusQueue extends Queue<string>
constructor() {
super(STATUS_BAR_WIDTH);

this.length = STATUS_BAR_WIDTH;
this.fill(GRAY_LINE);
for (let i = 0; i < STATUS_BAR_WIDTH; i++){
this.enqueue(GRAY_LINE);
}
}

public toString()
{
return this.join('');
return this.toArray().join('');
}
}

Expand Down
83 changes: 80 additions & 3 deletions src/services/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {join, resolve} from 'path';
import {test} from 'ava';
import {flatten, forp, FileSystemIterator} from './utils';
import {flatten, forp, FileSystemIterator, Queue} from './utils';

const NO_OP = () => { };
const TEST_DIR = resolve(__dirname, '../../test');

console.log(`The TEST_DIR is "${TEST_DIR}"."`);
console.log(`The TEST_DIR is "${TEST_DIR}".`);

test(`'flatten' returns the same array if already flattened`, t => {
let input = [2, 4, 6, 8];
Expand Down Expand Up @@ -142,4 +142,81 @@ test(`'FileSystemIterator.map' converts provided paths`, t => {
}
});
});
});
});

test(`'Queue' is a class`, t => {
t.is(typeof Queue, 'function');
});

test(`'Queue' requires no options`, t => {
t.notThrows(() => new Queue<Date>());
});

test(`'Queue' accepts an optional limit`, t => {
let q = new Queue<Date>(3);
t.is(q.limit, 3);
});

test(`'Queue' limit is enforced during enqueue.`, t => {
let q = new Queue<Date>(3);
q.enqueue(new Date());
t.is(q.count, 1);
q.enqueue(new Date());
t.is(q.count, 2);
q.enqueue(new Date());
t.is(q.count, 3);
q.enqueue(new Date());
t.is(q.count, 3);
});

test(`'Queue' limit is enforced after limit changed.`, t => {
let q = new Queue<Date>(5);
q.enqueue(new Date());
t.is(q.count, 1);
q.enqueue(new Date());
t.is(q.count, 2);
q.enqueue(new Date());
t.is(q.count, 3);
q.enqueue(new Date());
t.is(q.count, 4);
q.limit = 3;
t.is(q.count, 3);
});

test(`'Queue' is FIFO`, async (t) => {
let d1 = new Date();
await delay(100);
let d2 = new Date();
await delay(100);
let d3 = new Date();
await delay(100);
let d4 = new Date();

let q = new Queue<Date>(3);
t.is(q.count, 0);
q.enqueue(d1);
t.is(q.count, 1);
q.enqueue(d2);
t.is(q.count, 2);
q.enqueue(d3);
t.is(q.count, 3);
q.enqueue(d4);
t.is(q.count, 3);
t.deepEqual(q.toArray(), [d2, d3, d4]);
});

test(`'Queue.toString' is the same as Array.toString`, t => {
let q = new Queue<Date>();
q.enqueue(new Date());
q.enqueue(new Date());
q.enqueue(new Date());
t.is(q.toString(), q.toArray().toString());
});

function delay(duration: number): Promise<void> {
return new Promise<void>((resolve, reject) => {
setTimeout(() => {
resolve();
}, duration);
});
}

0 comments on commit 66c715e

Please sign in to comment.