2014-06-25 hubot-mock-adapter をためした
hubot-scripts hello をつくった。その過程で hubot-mock-adapter をためした。
hello.js は faithcreates/hubot-scripts にあったもの。faithcreates/sushi へ移植している。
今回の移植では、次のことに対応した。
- JavaScript -> CoffeeScript
- テストの追加
前者は簡単だ。もともとほとんど行数がないので、一瞬で終わる。問題は後者のテストである。
スクリプトに渡される robot を mock すればいいのだけど、そうすると正しく動くのかが怪しくなるので、hubot-mock-adapter で adapter を mock する。
# hubot スクリプトの例
module.exports = (robot) ->
robot.respond /hello$/i, (res) ->
res.send 'hello'
hubot-url について書いた時にもふれたのだけど、hubot-mock-adapter は機能が弱い。hubot-mock-adapter の README を見ればわかるが、やりたいことの割に記述が冗長すぎる。なので、Hubot 自体と hubot-mock-adapter を扱うための robot-driver をつくった。
まだ汎用性が低いためイマイチだが、汎用化できれば npm に公開したい。
{Promise} = require 'q'
{Robot, TextMessage} = require 'hubot'
class RobotDriver
TIMEOUT = 100 # ms
constructor: ->
@robot = null # initialize in start()
@adapter = null # initialize in start()
@started = false
@users = []
start: (options) ->
throw new Error('already started') if @started
@started = true
new Promise (resolve, reject) =>
@robot = new Robot(null, 'mock-adapter', false, 'sushi')
@robot.adapter.on 'connected', =>
@adapter = @robot.adapter
(options.scripts or []).forEach (script) =>
script @robot
(options.users or []).forEach (user) =>
@users.push @robot.brain.userForId(user.id, {
name: user.name,
room: user.room
})
resolve()
@robot.run()
stop: ->
throw new Error('call receiveMessage() after start()') unless @started
@robot.shutdown()
Promise.resolve()
receiveMessage: (envelope, message) ->
throw new Error('call receiveMessage() after start()') unless @started
promise = new Promise (resolve, reject) =>
setTimeout ->
reject new Error('timeout')
, TIMEOUT
@adapter.on 'send', (envelope, strings) ->
resolve
name: 'send'
envelope: envelope
strings: strings
@adapter.receive new TextMessage(envelope, message)
promise
module.exports = RobotDriver