hubot-pretend
Version:
Test Hubot scripts with a mock robot, rooms and users.
348 lines (312 loc) • 10.7 kB
JavaScript
;Object.defineProperty(exports, "__esModule", { value: true });
var _fs = require('fs');var _fs2 = _interopRequireDefault(_fs);
var _path = require('path');var _path2 = _interopRequireDefault(_path);
var _lodash = require('lodash');var _lodash2 = _interopRequireDefault(_lodash);
var _robot = require('./robot');var _robot2 = _interopRequireDefault(_robot);
var _user = require('./user');var _user2 = _interopRequireDefault(_user);
var _room = require('./room');var _room2 = _interopRequireDefault(_room);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}
// prevent issues with default port in use
if (!(process.env.PORT || process.env.EXPRESS_PORT)) process.env.PORT = '3000';
// init vars
let robot, users, rooms, scripts;
// option fallbacks
const defaults = {
httpd: false,
name: 'hubot',
alias: false,
rooms: null,
users: null
/**
* Read in scripts from path/s, will overwrite any previous reads.
*
* @param {array|string} scriptPaths Paths to read for loading into hubot
* @return {pretend} Self for chaining
*/ };
function read(scriptPaths) {
scripts = [];
if (!Array.isArray(scriptPaths)) scriptPaths = [scriptPaths];
for (let scriptPath of scriptPaths) {
// get scripts if file path given, or all from directory
scriptPath = _path2.default.resolve(scriptPath);
if (_fs2.default.statSync(scriptPath).isDirectory()) {
for (let file of _fs2.default.readdirSync(scriptPath).sort()) {
scripts.push({
path: scriptPath,
file: file });
}
} else {
scripts.push({
path: _path2.default.dirname(scriptPath),
file: _path2.default.basename(scriptPath) });
}
}
// robot, load scripts
load();
return this;
}
/**
* Start (or restart) collections and create pretend robot.
*
* @param {Object} [options={}] Config object, optional attributes:
* @param {boolean} [options.httpd] Enable server (default: false)
* @param {string} [options.name] Robot name
* @param {string} [options.alias] Robot alias
* @param {array} [options.rooms] Room names to start with
* @param {array} [options.rooms] User names to start with
* @return {pretend} Self for chaining
*/
function start() {let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
let config = Object.assign({}, defaults, options);
// reset test user/room collections
users = {};
rooms = {};
// force a log level if given in options
if (options.logLevel) process.env.HUBOT_LOG_LEVEL = options.logLevel;
// create robot
// TODO: update to options object when that happens in hubot core
robot = new _robot2.default(config.httpd, config.name, config.alias);
// create users and rooms as per config options
if (config.rooms != null) config.rooms.map(r => room(r));
if (config.users != null) config.users.map(u => user(u));
// tell robot to load and go
robot.run(); // run before load, so scripts can extend robot after pretend does
load();
return this;
}
/**
* Shortcut to robot shutdown
* @return {pretend} Self for chaining
*/
function shutdown() {
if (robot) robot.shutdown();
reset();
return this;
}
/**
* Reset (or init) robot and collection vars, for after tests clean up.
*/
function reset() {
robot = null;
users = {};
rooms = {};
}
reset();
/**
* Clear read-in scripts, to ensure nothing loaded on next `.start()`.
*
* @return {pretend} Self for chaining
*/
function clear() {
scripts = [];
return this;
}
/**
* Load any read-in scripts (if robot created and script not already read).
*
* @return {pretend} Self for chaining
*/
function load() {
if (robot === null) return;
let scriptsToLoad = _lodash2.default.differenceBy(scripts, robot.loaded, _lodash2.default.isEqual);
scriptsToLoad.map(s => robot.loadFile(s.path, s.file));
return this;
}
/**
* Send message from a given user (through adapter).
*
* @param {User} user The user
* @param {Message} message Hubot message object
* @return {Promise} Promise resolving when receive middleware complete
*/
function userSend(user, message) {
return robot.adapter.receive(user, message);
}
/**
* Send an enter message from a given user.
*
* @param {User} user The user (assumes with room already set)
* @return {Promise} Promise resolving when receive middleware complete
*/
function userEnter(user) {
return robot.adapter.enter(user);
}
/**
* Send a leave message to robot from user.
*
* @param {User} user The user (assumes with room already set)
* @return {Promise} Promise resolving when receive middleware complete
*/
function userLeave(user) {
return robot.adapter.leave(user);
}
/**
* Get any private message entries in adapter assigned to username.
*
* @param {User} user The user
* @return {array} Private messages for user
*/
function userPrivates(user) {
return robot.adapter.privateMessages[user.name];
}
/**
* Get filtered array of given room's messages from adapter.
*
* @return {array} Messages [user, message] sent to room
*/
function roomMessages(room) {
let messages = _lodash2.default.filter(robot.adapter.messages, msg => msg[0] === room.name);
return _lodash2.default.map(messages, _lodash2.default.drop); // truncates room column from messages
}
/**
* Send message through adapter, coming from given room and user.
*
* @param {Room} room Source room
* @param {User} user Source user
* @param {Message} message The message
* @return {Promise} Promise resolving when receive middleware complete
*/
function roomReceive(room, user, message) {
return robot.adapter.receive(user.in(room), message);
}
/**
* Send enter message for given user in given room.
*
* @param {Room} room Source room
* @param {User} user Source user
* @return {Promise} Promise resolving when receive middleware complete
*/
function roomEnter(room, user) {
return userEnter(user.in(room));
}
/**
* Send leave message for given user in given room.
*
* @param {Room} room Source room
* @param {User} user Source user
* @return {Promise} Promise resolving when receive middleware complete
*/
function roomLeave(room, user) {
return userLeave(user.in(room));
}
/**
* Create or get existing user, for entering/leaving and sending messages.
*
* Extend with methods routing to pretend helpers with this user provided.
*
* @param {string} name Name for the user
* @param {Object} [options={}] Optional attributes for user
* @return {User} A new user instance with adapter helpers
*/
function user(name) {let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (!(0, _lodash2.default)(users).keys().includes(name)) {
options.name = name;
let user = new _user2.default(options);
user.send = function (message) {
return userSend(this, message);
};
user.enter = function () {
return userEnter(this);
};
user.leave = function () {
return userLeave(this);
};
user.privates = function () {
return userPrivates(this);
};
users[name] = user;
}
return users[name];
}
/**
* Create or get existing room, for entering/leaving and receiving messages.
*
* Extend with methods routing to pretend helpers with this room provided.
*
* @param {string} name Name for the room
* @return {Room} A new room instance with adapter helpers
*/
function room(name) {
if (!(0, _lodash2.default)(rooms).keys().includes(name)) {
let room = new _room2.default(name);
room.messages = function () {
return roomMessages(this);
};
room.receive = function (user, message) {
return roomReceive(this, user, message);
};
room.enter = function (user) {
return roomEnter(room, user);
};
room.leave = function (user) {
return roomLeave(this, user);
};
rooms[name] = room;
}
return rooms[name];
}
/**
* Shortcut for sending/receiving just to get the latest response object,
* which also may require async, instead just make one as required for tests.
*
* This response will not be in `pretend.responses` and message will not appear
* in `pretend.messages`.
*
* @param {string} username Name for user to get/create as response origin
* @param {string} text Text for creating message instance
* @param {string} [room] Room name (optional) to add to user object
* @return {MockResponse} A mock response instance
*/
function response(username, text) {let room = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
return robot.adapter.response(user(username, { room: room }), text);
}
/**
* Helper, retrieves the latest res before listens matched or not.
*
* @return {MockResponse} A mock response instance
*/
function lastReceive() {
return robot.responses.receive.slice(-1).pop();
}
/**
* Helper, retrieves the latest res from user matching a listener.
*
* @return {MockResponse} A mock response instance
*/
function lastListen() {
return robot.responses.listen.slice(-1).pop();
}
/**
* Helper, retrieves the latest res from a hubot sent response.
*
* @return {MockResponse} A mock response instance
*/
function lastRespond() {
return robot.responses.respond.slice(-1).pop();
}
// Revealed API, uses getters to return current state of collections.
exports.default = {
startup: start, // support pre-release method
start: start,
read: read,
clear: clear,
load: load,
shutdown: shutdown,
user: user,
room: room,
response: response,
lastReceive: lastReceive,
lastListen: lastListen,
lastRespond: lastRespond,
get users() {return users;},
get rooms() {return rooms;},
get scripts() {return scripts;},
get robot() {return robot;},
get http() {return robot.http;},
get adapter() {return robot.adapter;},
get messages() {return robot.adapter.messages;},
get observer() {return robot.adapter.observer;},
get responses() {return robot.responses;},
get events() {return robot.eventLog;},
get log() {return robot.logger;},
get logs() {return robot.logger.logs;} };module.exports = exports['default'];
//# sourceMappingURL=pretend.js.map