Skip to content

Commit

Permalink
add extended help registration ability
Browse files Browse the repository at this point in the history
  • Loading branch information
AccaliaDeElementia committed Jan 17, 2016
1 parent 7e19fc0 commit 26021a1
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 16 deletions.
37 changes: 34 additions & 3 deletions lib/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ const internals = {
parseShortCommand: parseShortCommand,
parseMentionCommand: parseMentionCommand,
registerCommand: registerCommand,
registerHelp: registerHelp,
events: null,
commandProtect: commandProtect,
getCommandHelps: getCommandHelps,
cmdError: cmdError,
cmdHelp: cmdHelp,
cmdShutUp: cmdShutUp,
shutdown: shutdown,
commands: {}
commands: {},
helpMessages: {}
};

/**
Expand All @@ -41,6 +43,7 @@ exports.prepare = function prepare(events, callback) {
events.on('command#ERROR', cmdError);
events.onCommand = registerCommand;
events.on('newListener', commandProtect);
events.registerHelp = registerHelp;
async.parallel([
cb => events.onCommand('help', 'print command help listing', cmdHelp, cb),
cb => events.onCommand('shutup', 'tell me to shutup', cmdShutUp, cb),
Expand Down Expand Up @@ -202,8 +205,18 @@ function cmdHelp(command) {
if (!command.post) {
return;
}
const help = internals.getCommandHelps() + '\n\nMore details may be available by passing `help` as ' +
'the first parameter to a command';
let ext = '';
if (command.args && command.args.length > 0) {
ext = command.args.join(' ');
}
if (ext && internals.helpMessages[ext]) {
const txt = 'Extended help for `' + ext + '`\n\n' + internals.helpMessages[ext] +
'\n\nIssue the `help` command without any parameters to see all available commands';
browser.createPost(command.post.topic_id, command.post.post_number, txt, () => 0);
return;
}
const help = internals.getCommandHelps() + '\n\nMore details may be available by passing a command name as ' +
'the first parameter to `help`';
browser.createPost(command.post.topic_id, command.post.post_number, help, () => 0);
}

Expand Down Expand Up @@ -244,6 +257,24 @@ function registerCommand(command, helpstring, handler, callback) {
return callback();
}

function registerHelp(command, helptext, callback) {
if (!callback || typeof callback !== 'function') {
throw new Error('callback must be provided');
}
if (!command || typeof command !== 'string') {
return callback(new Error('command must be provided'));
}
if (!helptext || typeof helptext !== 'string') {
return callback(new Error('helptext must be provided'));
}
if (internals.helpMessages[command]) {
internals.events.emit('logWarning', 'Overwriting existing extended help for: `' + command + '`!');
}
internals.helpMessages[command] = helptext;
internals.events.emit('logMessage', 'Extended help registered for: ' + command);
return callback();
}

/**
* Watch for unauthorized commands and reject them
*
Expand Down
18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,24 @@
"filesize": "^3.1.5",
"js-yaml": "^3.5.2",
"knuth-shuffle": "^1.0.1",
"later": "^1.1.9",
"request": "^2.60.0",
"later": "^1.2.0",
"request": "^2.67.0",
"xregexp": "^3.0.0",
"yargs": "^3.24.0"
"yargs": "^3.32.0"
},
"devDependencies": {
"blns": "^2.0.1",
"chai": "^3.2.0",
"blns": "^2.0.2",
"chai": "^3.4.1",
"chai-string": "^1.1.6",
"coveralls": "^2.11.6",
"gulp": "^3.9.0",
"gulp-eslint": "^1.0.0",
"gulp-eslint": "^1.1.1",
"gulp-git": "^1.6.1",
"gulp-istanbul": "^0.10.0",
"gulp-istanbul": "^0.10.3",
"gulp-jsdoc-to-markdown": "^1.2.1",
"gulp-mocha": "^2.1.3",
"gulp-rename": "^1.2.2",
"sinon": "^1.15.1",
"gulp-rename": "^1.2.2",
"sinon": "^1.17.2",
"sinon-chai": "^2.8.0"
},
"scripts": {
Expand Down
167 changes: 163 additions & 4 deletions test/lib/commandsTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ describe('commands', () => {
});
});
describe('internals', () => {
const fns = ['parseMentionCommand', 'parseShortCommand', 'registerCommand',
const fns = ['parseMentionCommand', 'parseShortCommand', 'registerCommand', 'registerHelp',
'commandProtect', 'getCommandHelps', 'cmdError', 'cmdHelp', 'cmdShutUp',
'shutdown'
],
objs = ['mention', 'events', 'commands'],
objs = ['mention', 'events', 'commands', 'helpMessages'],
vals = [];
describe('should include expected functions:', () => {
fns.forEach((fn) => {
Expand Down Expand Up @@ -183,8 +183,8 @@ describe('commands', () => {
});
it('should post expected text', () => {
const expected = 'Registered commands:\nhelp: print command help listing\n' +
'shutup: tell me to shutup\n\nMore details may be available by passing' +
' `help` as the first parameter to a command';
'shutup: tell me to shutup\n\nMore details may be available by passing ' +
'a command name as the first parameter to `help`';
commands.internals.commands.help = {
help: 'print command help listing'
};
Expand Down Expand Up @@ -213,6 +213,93 @@ describe('commands', () => {
browser.createPost.lastCall.args[3].should.be.a('function');
browser.createPost.lastCall.args[3]().should.equal(0);
});
describe('with parameters', () => {
it('should post default text without parameters', () => {
const expected = 'Registered commands:';
cmdHelp({
command: 'foobar',
post: {
'topic_id': 15,
'post_number': 75
}
});
browser.createPost.callCount.should.equal(1);
browser.createPost.calledWith(15, 75).should.be.true;
browser.createPost.lastCall.args[2].should.startWith(expected);
});
it('should post default text when called with empty parameters', () => {
const expected = 'Registered commands:';
cmdHelp({
command: 'foobar',
args: [],
post: {
'topic_id': 15,
'post_number': 75
}
});
browser.createPost.callCount.should.equal(1);
browser.createPost.calledWith(15, 75).should.be.true;
browser.createPost.lastCall.args[2].should.startWith(expected);
});
it('should post default text when called with unexpected parameters', () => {
const expected = 'Registered commands:';
cmdHelp({
command: 'foobar',
args: ['i', 'am', 'not', 'a', 'command'],
post: {
'topic_id': 15,
'post_number': 75
}
});
browser.createPost.callCount.should.equal(1);
browser.createPost.calledWith(15, 75).should.be.true;
browser.createPost.lastCall.args[2].should.startWith(expected);
});
it('should post extended help message one word command', () => {
const expected = 'Extended help for `whosit`\n\nwhosit extended help' +
'\n\nIssue the `help` command without any parameters to see all available commands';
commands.internals.helpMessages.whosit = 'whosit extended help';
cmdHelp({
command: 'foobar',
args: ['whosit'],
post: {
'topic_id': 15,
'post_number': 75
}
});
browser.createPost.callCount.should.equal(1);
browser.createPost.calledWith(15, 75).should.be.true;
browser.createPost.lastCall.args[2].should.equal(expected);
});
it('should post extended help message multi-word command', () => {
const expected = 'Extended help for `who am i`';
commands.internals.helpMessages['who am i'] = 'whosit extended help';
cmdHelp({
command: 'foobar',
args: ['who', 'am', 'i'],
post: {
'topic_id': 15,
'post_number': 75
}
});
browser.createPost.callCount.should.equal(1);
browser.createPost.calledWith(15, 75).should.be.true;
browser.createPost.lastCall.args[2].should.startWith(expected);
});
it('should pass callback to createPost', () => {
commands.internals.helpMessages['who am i'] = 'whosit extended help';
cmdHelp({
command: 'foobar',
args: ['who', 'am', 'i'],
post: {
'topic_id': 1,
'post_number': 5
}
});
browser.createPost.lastCall.args[3].should.be.a('function');
browser.createPost.lastCall.args[3]().should.equal(0);
});
});
});
describe('internals.cmdShutUp()', () => {
const cmdShutUp = commands.internals.cmdShutUp;
Expand Down Expand Up @@ -615,6 +702,78 @@ describe('commands', () => {
cmd.args.should.deep.equal(['arg1', 'arg2']);
});
});
describe('internals.registerHelp()', () => {
const registerHelp = commands.internals.registerHelp,
spy = sinon.spy();
let sandbox, events;
beforeEach(() => {
sandbox = sinon.sandbox.create();
events = {
on: sinon.spy(),
emit: sinon.spy()
};
commands.internals.events = events;
commands.internals.commands = {};
});
afterEach(() => {
sandbox.restore();
});
describe('parameter validation', () => {
it('should require a callback', () => {
expect(() => registerHelp()).to.throw('callback must be provided');
});
it('should require callback to be a function', () => {
expect(() => {
registerHelp(undefined, undefined, 'not function');
}).to.throw('callback must be provided');
});
it('should require `command`', () => {
registerHelp(undefined, undefined, spy);
spy.called.should.be.true;
spy.lastCall.args[0].should.be.instanceOf(Error);
spy.lastCall.args[0].message.should.equal('command must be provided');
});
it('should require `command` to be string', () => {
registerHelp(true, undefined, spy);
spy.called.should.be.true;
spy.lastCall.args[0].should.be.instanceOf(Error);
spy.lastCall.args[0].message.should.equal('command must be provided');
});
it('should require `helptext`', () => {
registerHelp('command', undefined, spy);
spy.called.should.be.true;
spy.lastCall.args[0].should.be.instanceOf(Error);
spy.lastCall.args[0].message.should.equal('helptext must be provided');
});
it('should require `helptext` to be string', () => {
registerHelp('command', true, spy);
spy.called.should.be.true;
spy.lastCall.args[0].should.be.instanceOf(Error);
spy.lastCall.args[0].message.should.equal('helptext must be provided');
});
it('should call callback without error on help registration', () => {
registerHelp('command', 'help', spy);
spy.called.should.be.true;
spy.lastCall.args.should.have.length(0);
});
});
it('should add command to help Messages on registration', () => {
registerHelp('commandhelp', 'help', spy);
commands.internals.helpMessages.commandhelp.should.be.ok;
});
it('should log registration', () => {
const cmd = 'CMD' + Math.random();
registerHelp(cmd, 'help', spy);
events.emit.calledWith('logMessage', 'Extended help registered for: ' + cmd).should.be.true;
});
it('should warn on help overwrite', () => {
const cmd = 'CMD' + Math.random();
commands.internals.helpMessages[cmd] = 'foo';
registerHelp(cmd, 'help', spy);
events.emit.calledWith('logWarning', 'Overwriting existing extended help for: `' + cmd +
'`!').should.be.true;
});
});
describe('internals.registerCommand()', () => {
const registerCommand = commands.internals.registerCommand,
spy = sinon.spy();
Expand Down

0 comments on commit 26021a1

Please sign in to comment.