lita 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +54 -15
- data/lib/lita/adapters/shell.rb +2 -1
- data/lib/lita/handler.rb +34 -0
- data/lib/lita/message.rb +3 -1
- data/lib/lita/robot.rb +12 -0
- data/lib/lita/rspec/handler.rb +50 -2
- data/lib/lita/source.rb +41 -8
- data/lib/lita/version.rb +1 -1
- data/spec/lita/adapters/shell_spec.rb +6 -0
- data/spec/lita/handler_spec.rb +22 -0
- data/spec/lita/message_spec.rb +2 -2
- data/spec/lita/robot_spec.rb +18 -5
- data/spec/lita/rspec_spec.rb +8 -0
- data/spec/lita/source_spec.rb +33 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0f46a0926eb20ff35d1597e8d7474e64984ffd4
|
4
|
+
data.tar.gz: 63b751e98f2e477e41b144da5c731160963d2377
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f594e6d3301112d652d22b03c3f280c2560a7a86ab6868369d6240c3816cee6500db31c9737268850be6f04257c895baf27c4f06840a727ec95f93554d93824
|
7
|
+
data.tar.gz: 189688873d5ed9c3c110c0114b47ce94267ea4a7ea66f0c455652363f2433e18fed60e99ae792232e329eadb08f20ea6aeb77a2cb3eef4225f7412343582ec24
|
data/README.md
CHANGED
@@ -18,6 +18,7 @@ Automate your business and have fun with your very own robot companion.
|
|
18
18
|
* Easily extendable with plugins
|
19
19
|
* Data persistence with Redis
|
20
20
|
* Built-in web server and routing
|
21
|
+
* Event system for behavior triggered in response to arbitrary events
|
21
22
|
* Support for outgoing HTTP requests
|
22
23
|
* Group-based authorization
|
23
24
|
* Configurable logging
|
@@ -183,7 +184,7 @@ For more detailed examples, check out the built in shell adapter, [lita-hipchat]
|
|
183
184
|
|
184
185
|
## Writing a handler
|
185
186
|
|
186
|
-
A handler is packaged as a RubyGem. A handler is a class that inherits from `Lita::Handler` and is registered by calling `Lita.register_handler(TheHandlerClass)`. There are two components to a handler: route definitions, and the methods that implement those routes. There are
|
187
|
+
A handler is packaged as a RubyGem. A handler is a class that inherits from `Lita::Handler` and is registered by calling `Lita.register_handler(TheHandlerClass)`. There are two components to a handler: route definitions, and the methods that implement those routes. There are chat routes, HTTP routes, and event subscriptions available to handlers.
|
187
188
|
|
188
189
|
To generate a starting template for a new handler gem, run `lita handler NAME`, where NAME is the name of the new gem.
|
189
190
|
|
@@ -239,6 +240,27 @@ def baz(request, response)
|
|
239
240
|
end
|
240
241
|
```
|
241
242
|
|
243
|
+
### Event subscriptions
|
244
|
+
|
245
|
+
Handlers can communicate with each other or respond to arbitrary system events with the built-in pub-sub event system. Subscribe to an event by name, and provide the name of the instance method that should be invoked when the event triggers. Event callback methods are passed a payload hash with any arbitrary data the caller chooses to provide.
|
246
|
+
|
247
|
+
``` ruby
|
248
|
+
on :connected, :greet
|
249
|
+
|
250
|
+
def greet(payload)
|
251
|
+
target = Source.new(room: payload[:room])
|
252
|
+
robot.send_message(target, "Hello #{payload[:room]}!")
|
253
|
+
end
|
254
|
+
```
|
255
|
+
|
256
|
+
Trigger an event from anywhere and pass any payload data you want the subscribed handlers to receive:
|
257
|
+
|
258
|
+
``` ruby
|
259
|
+
robot.trigger(:connected, room: "#litabot")
|
260
|
+
```
|
261
|
+
|
262
|
+
Since the `trigger` method is available on `Lita::Robot`, it can be used from anywhere in the Lita runtime (both adapters and handlers).
|
263
|
+
|
242
264
|
### Handler-specific configuration
|
243
265
|
|
244
266
|
If you want your handler to expose config settings to the user, use the class-level `default_config` method. This method accepts a single config object as an argument, which will be exposed to the user as `Lita.config.handlers.your_handler_namespace`.
|
@@ -318,30 +340,47 @@ For more detailed examples, check out the built in authorization, help, and web
|
|
318
340
|
|
319
341
|
## Testing
|
320
342
|
|
321
|
-
It's a core philosophy of Lita that any plugins you write for your robot should be as thoroughly tested as any other program you would write. To make this easier, Lita ships with some handy extras for [RSpec](https://github.com/rspec/rspec) that make testing a
|
343
|
+
It's a core philosophy of Lita that any plugins you write for your robot should be as thoroughly tested as any other program you would write. To make this easier, Lita ships with some handy extras for [RSpec](https://github.com/rspec/rspec) that make testing a plugin dead simple. They require the full RSpec suite (rspec-core, rspec-expectations, and rspec-mocks) version 2.14 or higher, as they use the newer "expect" syntax.
|
322
344
|
|
323
|
-
### Testing
|
345
|
+
### Testing adapters
|
324
346
|
|
325
|
-
To include
|
347
|
+
To include some helpful setup for testing Lita code, require "lita/rspec", then add `lita: true` to the metadata for an example group.
|
326
348
|
|
327
349
|
``` ruby
|
328
350
|
require "lita/rspec"
|
329
351
|
|
330
|
-
describe Lita::
|
352
|
+
describe Lita::Adapters::MyAdapter, lita: true do
|
331
353
|
# ...
|
332
354
|
end
|
333
355
|
```
|
334
356
|
|
335
|
-
This
|
357
|
+
This will have the following effects:
|
336
358
|
|
337
359
|
* All Redis interaction will be namespaced to a test environment and automatically cleared out before each example.
|
338
360
|
* Lita's logger is stubbed to prevent log messages from cluttering up your test output.
|
339
361
|
* Lita's configuration is cleared out before each example, so that the first call to `Lita.config` will start from the default configuration.
|
362
|
+
|
363
|
+
### Testing handlers
|
364
|
+
|
365
|
+
To include Lita's RSpec extras for testing a handler, require "lita/rspec", then add `lita_handler: true` to the metadata for the example group.
|
366
|
+
|
367
|
+
``` ruby
|
368
|
+
require "lita/rspec"
|
369
|
+
|
370
|
+
describe Lita::Handlers::MyHandler, lita_handler: true do
|
371
|
+
# ...
|
372
|
+
end
|
373
|
+
```
|
374
|
+
|
375
|
+
This will have the following effects, in addition to the effects of the `lita: true` metadata hook:
|
376
|
+
|
340
377
|
* `Lita.handlers` will return an array with only the class you're testing (`described_class`).
|
341
378
|
* Strings sent with `Lita::Robot#send_messages` will be pushed to an array accessible as `replies` so you can make expectations about output from the robot.
|
342
379
|
* You have access to the following cached objects set with `let`: `robot`, `source`, and `user`. Note that these objects are instances of the real classes and not test doubles.
|
343
380
|
|
344
|
-
The custom helper methods are where `Lita::RSpec` really shines. You can test routes (both chat and HTTP routes) very easily using this syntax:
|
381
|
+
The custom helper methods are where `Lita::RSpec` really shines. You can test routes (both chat and HTTP routes) and event subscriptions very easily using this syntax:
|
382
|
+
|
383
|
+
#### Testing routes
|
345
384
|
|
346
385
|
``` ruby
|
347
386
|
it { routes("some message").to(:some_method) }
|
@@ -349,6 +388,8 @@ it { routes_command("directed message").to(:some_command_method) }
|
|
349
388
|
it { doesnt_route("message").to(:some_command_method) }
|
350
389
|
it { routes_http(:get, "/foo/bar").to(:baz) }
|
351
390
|
it { doesnt_route_http(:post, "/foo/bar").to(:baz) }
|
391
|
+
it { routes_event(:connected).to(:greet) }
|
392
|
+
it { doesnt_route_event(:some_other_event).to(:greet) }
|
352
393
|
```
|
353
394
|
|
354
395
|
* `routes` - Sets an expectation that the given string will trigger the given method when overheard by the robot.
|
@@ -357,9 +398,15 @@ it { doesnt_route_http(:post, "/foo/bar").to(:baz) }
|
|
357
398
|
* `doesnt_route_command` - Sets an expectation that is the inverse of the one set by `routes_command`. Also aliased to `does_not_route_command`.
|
358
399
|
* `routes_http` - Sets an expectation that an HTTP request with the given HTTP method and path will route to the given handler method.
|
359
400
|
* `doesnt_route_http` - Sets an expectation that is the inverse of `routes_http`. Also aliased to `does_not_route_http`.
|
401
|
+
* `routes_event` - Sets an expectation that the given event will trigger the given subscribed method.
|
402
|
+
* `doesnt_route_event` - Sets an expectation that is the inverse of `routes_event`. Also aliased to `does_not_route_event`.
|
360
403
|
|
361
404
|
**Note: These routing helpers bypass authorization for routes restricted to authorization groups.**
|
362
405
|
|
406
|
+
#### Testing handler methods
|
407
|
+
|
408
|
+
Since the behavior in handlers are regular instance methods, you can unit test them just as you would any other methods in a Ruby class. However, if you prefer a more integration test approach, there are some helper methods available to help with this.
|
409
|
+
|
363
410
|
To send a message to the robot, use `send_message` and `send_command`. Then set expectations about the contents of the `replies` array.
|
364
411
|
|
365
412
|
``` ruby
|
@@ -387,14 +434,6 @@ end
|
|
387
434
|
* `send_message(string, as: user)` - Sends the given string to the robot.
|
388
435
|
* `send_command(string, as: user)` - Sends the given string to the robot, prefixing it with the robot's mention name.
|
389
436
|
|
390
|
-
### Testing adapters or other code
|
391
|
-
|
392
|
-
If you use `lita: true` instead of `lita_handler: true` in the metadata for your example group, only a small subset of Lita's RSpec extras will be enabled:
|
393
|
-
|
394
|
-
* All Redis interaction will be namespaced to a test environment and automatically cleared out before each example.
|
395
|
-
* Lita's logger is stubbed to prevent log messages from cluttering up your test output.
|
396
|
-
* Lita's configuration is cleared out before each example, so that the first call to `Lita.config` will start from the default configuration.
|
397
|
-
|
398
437
|
## Running as a daemon
|
399
438
|
|
400
439
|
Lita has built-in support for daemonization on Unix systems. When run as a daemon, Lita will redirect standard output and standard error to a log file, and write the process ID to a PID file. To start Lita as a daemon, run `lita -d`. There are additional command line flags for specifying the path of the log and PID files, which override the defaults. If an existing Lita process is running when `lita -d` is invoked, Lita will abort and leave the original process running, unless the `-k` flag is specified, in which case it will kill the existing process. Run `lita help` for information about all the possible command line flags.
|
data/lib/lita/adapters/shell.rb
CHANGED
@@ -7,8 +7,9 @@ module Lita
|
|
7
7
|
# @return [void]
|
8
8
|
def run
|
9
9
|
user = User.create(1, name: "Shell User")
|
10
|
-
source = Source.new(user)
|
10
|
+
source = Source.new(user: user)
|
11
11
|
puts 'Type "exit" or "quit" to end the session.'
|
12
|
+
robot.trigger(:connected)
|
12
13
|
|
13
14
|
loop do
|
14
15
|
print "#{robot.name} > "
|
data/lib/lita/handler.rb
CHANGED
@@ -95,8 +95,38 @@ module Lita
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
+
# Registers an event subscription. When an event is triggered with
|
99
|
+
# {trigger}, a new instance of the handler will be created and the
|
100
|
+
# instance method name supplied to {on} will be invoked with a payload
|
101
|
+
# (a hash of arbitrary keys and values).
|
102
|
+
# @param event_name [String, Symbol] The name of the event to subscribe
|
103
|
+
# to.
|
104
|
+
# @param method_name [String, Symbol] The name of the instance method on
|
105
|
+
# the handler that should be invoked when the event is triggered.
|
106
|
+
# @return [void]
|
107
|
+
def on(event_name, method_name)
|
108
|
+
event_subscriptions[normalize_event(event_name)] << method_name
|
109
|
+
end
|
110
|
+
|
111
|
+
# Triggers an event, invoking methods previously registered with {on} and
|
112
|
+
# passing them a payload hash with any arbitrary data.
|
113
|
+
# @param robot [Lita::Robot] The currently running robot instance.
|
114
|
+
# @param event_name [String, Symbol], The name of the event to trigger.
|
115
|
+
# @param payload [Hash] An optional hash of arbitrary data.
|
116
|
+
# @return [void]
|
117
|
+
def trigger(robot, event_name, payload = {})
|
118
|
+
event_subscriptions[normalize_event(event_name)].each do |method_name|
|
119
|
+
new(robot).public_send(method_name, payload)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
98
123
|
private
|
99
124
|
|
125
|
+
# A hash of arrays used to store event subscriptions registered with {on}.
|
126
|
+
def event_subscriptions
|
127
|
+
@event_subscriptions ||= Hash.new { |h, k| h[k] = [] }
|
128
|
+
end
|
129
|
+
|
100
130
|
# Determines whether or not an incoming messages should trigger a route.
|
101
131
|
def route_applies?(route, message, robot)
|
102
132
|
# Message must be a command if the route requires a command
|
@@ -141,6 +171,10 @@ LOG
|
|
141
171
|
#{e.backtrace.join("\n")}
|
142
172
|
ERROR
|
143
173
|
end
|
174
|
+
|
175
|
+
def normalize_event(event_name)
|
176
|
+
event_name.to_s.downcase.strip.to_sym
|
177
|
+
end
|
144
178
|
end
|
145
179
|
|
146
180
|
# @param robot [Lita::Robot] The currently running robot.
|
data/lib/lita/message.rb
CHANGED
@@ -74,7 +74,9 @@ module Lita
|
|
74
74
|
# @param strings [String, Array<String>] The strings to send back.
|
75
75
|
# @return [void]
|
76
76
|
def reply_privately(*strings)
|
77
|
-
|
77
|
+
private_source = source.clone
|
78
|
+
private_source.private_message!
|
79
|
+
@robot.send_messages(private_source, *strings)
|
78
80
|
end
|
79
81
|
end
|
80
82
|
end
|
data/lib/lita/robot.rb
CHANGED
@@ -71,6 +71,18 @@ module Lita
|
|
71
71
|
@adapter.shut_down
|
72
72
|
end
|
73
73
|
|
74
|
+
# Triggers an event, instructing all registered handlers to invoke any
|
75
|
+
# methods subscribed to the event, and passing them a payload hash of
|
76
|
+
# arbitrary data.
|
77
|
+
# @param event_name [String, Symbol] The name of the event to trigger.
|
78
|
+
# @param payload [Hash] An optional hash of arbitrary data.
|
79
|
+
# @return [void]
|
80
|
+
def trigger(event_name, payload = {})
|
81
|
+
Lita.handlers.each do |handler|
|
82
|
+
handler.trigger(self, event_name, payload)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
74
86
|
private
|
75
87
|
|
76
88
|
# Loads the selected adapter.
|
data/lib/lita/rspec/handler.rb
CHANGED
@@ -34,7 +34,7 @@ module Lita
|
|
34
34
|
def set_up_let_blocks(base)
|
35
35
|
base.class_eval do
|
36
36
|
let(:robot) { Robot.new }
|
37
|
-
let(:source) { Source.new(user) }
|
37
|
+
let(:source) { Source.new(user: user) }
|
38
38
|
let(:user) { User.create("1", name: "Test User") }
|
39
39
|
let(:replies) { [] }
|
40
40
|
end
|
@@ -56,7 +56,7 @@ module Lita
|
|
56
56
|
message = if as == user
|
57
57
|
Message.new(robot, body, source)
|
58
58
|
else
|
59
|
-
Message.new(robot, body, Source.new(as))
|
59
|
+
Message.new(robot, body, Source.new(user: as))
|
60
60
|
end
|
61
61
|
|
62
62
|
robot.receive(message)
|
@@ -136,6 +136,27 @@ module Lita
|
|
136
136
|
HTTPRouteMatcher.new(self, http_method, path, invert: true)
|
137
137
|
end
|
138
138
|
alias_method :doesnt_route_http, :does_not_route_http
|
139
|
+
|
140
|
+
# Starts an event subscription test chain, asserting that an event should
|
141
|
+
# trigger the target method.
|
142
|
+
# @param event_name [String, Symbol] The name of the event that should
|
143
|
+
# be triggered.
|
144
|
+
# @return [EventSubscriptionMatcher] An {EventSubscriptionMatcher} that
|
145
|
+
# should have +to+ called on it to complete the test.
|
146
|
+
def routes_event(event_name)
|
147
|
+
EventSubscriptionMatcher.new(self, event_name)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Starts an event subscription test chain, asserting that an event should
|
151
|
+
# not trigger the target method.
|
152
|
+
# @param event_name [String, Symbol] The name of the event that should
|
153
|
+
# not be triggered.
|
154
|
+
# @return [EventSubscriptionMatcher] An {EventSubscriptionMatcher} that
|
155
|
+
# should have +to+ called on it to complete the test.
|
156
|
+
def does_not_route_event(event_name)
|
157
|
+
EventSubscriptionMatcher.new(self, event_name, invert: true)
|
158
|
+
end
|
159
|
+
alias_method :doesnt_route_event, :does_not_route_event
|
139
160
|
end
|
140
161
|
|
141
162
|
# Used to complete a chat routing test chain.
|
@@ -190,5 +211,32 @@ module Lita
|
|
190
211
|
end
|
191
212
|
end
|
192
213
|
end
|
214
|
+
|
215
|
+
# Used to complete an event subscription test chain.
|
216
|
+
class EventSubscriptionMatcher
|
217
|
+
def initialize(context, event_name, invert: false)
|
218
|
+
@context = context
|
219
|
+
@event_name = event_name
|
220
|
+
@method = invert ? :not_to : :to
|
221
|
+
end
|
222
|
+
|
223
|
+
# Sets an expectation that a handler method will or will not be called in
|
224
|
+
# response to a triggered event, then triggers the event.
|
225
|
+
# @param target_method_name [String, Symbol] The name of the method that
|
226
|
+
# should or should not be triggered.
|
227
|
+
# @return [void]
|
228
|
+
def to(target_method_name)
|
229
|
+
e = @event_name
|
230
|
+
m = @method
|
231
|
+
|
232
|
+
@context.instance_eval do
|
233
|
+
expect_any_instance_of(described_class).public_send(
|
234
|
+
m,
|
235
|
+
receive(target_method_name)
|
236
|
+
)
|
237
|
+
robot.trigger(e)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
193
241
|
end
|
194
242
|
end
|
data/lib/lita/source.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
module Lita
|
2
|
-
# A wrapper object representing the source of an incoming message (the
|
3
|
-
# who sent it,
|
2
|
+
# A wrapper object representing the source of an incoming message (either the
|
3
|
+
# user who sent it, the room they sent it from, or both). If a room is set,
|
4
4
|
# the message is from a group chat room. If no room is set, the message is
|
5
|
-
# assumed to be a private message
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# assumed to be a private message, though Source objects can be explicitly
|
6
|
+
# marked as private messages. Source objects are also used as "target" objects
|
7
|
+
# when sending an outgoing message or performing another operation on a user
|
8
|
+
# or a room.
|
8
9
|
class Source
|
10
|
+
# A flag indicating that a message was sent to the robot privately.
|
11
|
+
# @return [Boolean] The boolean flag.
|
12
|
+
attr_reader :private_message
|
13
|
+
alias_method :private_message?, :private_message
|
9
14
|
|
10
15
|
# The room the message came from or should be sent to.
|
11
16
|
# @return [String] A string uniquely identifying the room.
|
@@ -20,9 +25,37 @@ module Lita
|
|
20
25
|
# @param room [String] A string uniquely identifying the room the user sent
|
21
26
|
# the message from, or the room where a reply should go. The format of
|
22
27
|
# this string will differ depending on the chat service.
|
23
|
-
|
24
|
-
|
25
|
-
|
28
|
+
# @param private_message [Boolean] A flag indicating whether or not the
|
29
|
+
# message was sent privately.
|
30
|
+
def initialize(*args)
|
31
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
32
|
+
|
33
|
+
@user = options[:user]
|
34
|
+
@room = options[:room]
|
35
|
+
@private_message = options[:private_message]
|
36
|
+
|
37
|
+
if args.size > 0
|
38
|
+
Lita.logger.warn <<-WARNING.chomp
|
39
|
+
Passing positional arguments to Source is deprecated. \
|
40
|
+
Use Source.new(user: user, room: room, private_message: pm) instead.
|
41
|
+
WARNING
|
42
|
+
@user = args[0] if args[0]
|
43
|
+
@room = args[1] if args[1]
|
44
|
+
end
|
45
|
+
|
46
|
+
if user.nil? && room.nil?
|
47
|
+
raise ArgumentError.new("Either a user or a room is required.")
|
48
|
+
end
|
49
|
+
|
50
|
+
@private_message = true if room.nil?
|
51
|
+
end
|
52
|
+
|
53
|
+
# Destructively marks the source as a private message, meaning an incoming
|
54
|
+
# message was sent to the robot privately, or an outgoing message should be
|
55
|
+
# sent to a user privately.
|
56
|
+
# @return [void]
|
57
|
+
def private_message!
|
58
|
+
@private_message = true
|
26
59
|
end
|
27
60
|
end
|
28
61
|
end
|
data/lib/lita/version.rb
CHANGED
@@ -8,6 +8,7 @@ describe Lita::Adapters::Shell do
|
|
8
8
|
allow(subject).to receive(:puts)
|
9
9
|
allow(subject).to receive(:print)
|
10
10
|
allow($stdin).to receive(:gets).and_return("foo", "exit")
|
11
|
+
allow(robot).to receive(:trigger)
|
11
12
|
allow(robot).to receive(:receive)
|
12
13
|
end
|
13
14
|
|
@@ -22,6 +23,11 @@ describe Lita::Adapters::Shell do
|
|
22
23
|
expect_any_instance_of(Lita::Message).to receive(:command!)
|
23
24
|
subject.run
|
24
25
|
end
|
26
|
+
|
27
|
+
it "triggers a connected event" do
|
28
|
+
expect(robot).to receive(:trigger).with(:connected)
|
29
|
+
subject.run
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
33
|
describe "#send_message" do
|
data/spec/lita/handler_spec.rb
CHANGED
@@ -19,6 +19,9 @@ describe Lita::Handler, lita: true do
|
|
19
19
|
|
20
20
|
http.get "web", :web
|
21
21
|
|
22
|
+
on :connected, :greet
|
23
|
+
on :some_hook, :test_payload
|
24
|
+
|
22
25
|
def foo(response)
|
23
26
|
end
|
24
27
|
|
@@ -35,6 +38,10 @@ describe Lita::Handler, lita: true do
|
|
35
38
|
raise "The developer of this handler's got a bug in their code!"
|
36
39
|
end
|
37
40
|
|
41
|
+
def greet(payload)
|
42
|
+
robot.send_message("Hi, #{payload[:name]}! Lita has started!")
|
43
|
+
end
|
44
|
+
|
38
45
|
def self.name
|
39
46
|
"Lita::Handlers::Test"
|
40
47
|
end
|
@@ -130,6 +137,21 @@ describe Lita::Handler, lita: true do
|
|
130
137
|
end
|
131
138
|
end
|
132
139
|
|
140
|
+
describe ".trigger" do
|
141
|
+
it "invokes methods registered with .on and passes an arbitrary payload" do
|
142
|
+
expect(robot).to receive(:send_message).with(
|
143
|
+
"Hi, Carl! Lita has started!"
|
144
|
+
)
|
145
|
+
handler_class.trigger(robot, :connected, name: "Carl")
|
146
|
+
end
|
147
|
+
|
148
|
+
it "normalizes the event name" do
|
149
|
+
expect(robot).to receive(:send_message).twice
|
150
|
+
handler_class.trigger(robot, "connected")
|
151
|
+
handler_class.trigger(robot, " ConNected ")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
133
155
|
describe "#http" do
|
134
156
|
it "returns a Faraday connection" do
|
135
157
|
expect(subject.http).to be_a(Faraday::Connection)
|
data/spec/lita/message_spec.rb
CHANGED
@@ -77,10 +77,10 @@ describe Lita::Message do
|
|
77
77
|
subject = described_class.new(
|
78
78
|
robot,
|
79
79
|
"Hello",
|
80
|
-
Lita::Source.new("Carl", "#room")
|
80
|
+
Lita::Source.new(user: "Carl", room: "#room")
|
81
81
|
)
|
82
82
|
expect(robot).to receive(:send_messages) do |source, *strings|
|
83
|
-
expect(source
|
83
|
+
expect(source).to be_a_private_message
|
84
84
|
expect(strings).to eq(["foo", "bar"])
|
85
85
|
end
|
86
86
|
subject.reply_privately("foo", "bar")
|
data/spec/lita/robot_spec.rb
CHANGED
@@ -9,15 +9,28 @@ describe Lita::Robot do
|
|
9
9
|
expect { subject }.to raise_error(SystemExit)
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
context "with registered handlers" do
|
13
13
|
let(:handler1) { double("Handler 1").as_null_object }
|
14
14
|
let(:handler2) { double("Handler 2").as_null_object }
|
15
15
|
|
16
|
-
|
16
|
+
before do
|
17
17
|
allow(Lita).to receive(:handlers).and_return([handler1, handler2])
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#receive" do
|
21
|
+
it "dispatches messages to every registered handler" do
|
22
|
+
expect(handler1).to receive(:dispatch).with(subject, "foo")
|
23
|
+
expect(handler2).to receive(:dispatch).with(subject, "foo")
|
24
|
+
subject.receive("foo")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#trigger" do
|
29
|
+
it "triggers the supplied event on all registered handlers" do
|
30
|
+
expect(handler1).to receive(:trigger).with(subject, :foo, bar: "baz")
|
31
|
+
expect(handler2).to receive(:trigger).with(subject, :foo, bar: "baz")
|
32
|
+
subject.trigger(:foo, bar: "baz")
|
33
|
+
end
|
21
34
|
end
|
22
35
|
end
|
23
36
|
|
data/spec/lita/rspec_spec.rb
CHANGED
@@ -7,6 +7,8 @@ handler_class = Class.new(Lita::Handler) do
|
|
7
7
|
|
8
8
|
http.get "web", :web
|
9
9
|
|
10
|
+
on :connected, :greet
|
11
|
+
|
10
12
|
def foo(response)
|
11
13
|
response.reply "baz"
|
12
14
|
end
|
@@ -21,6 +23,9 @@ handler_class = Class.new(Lita::Handler) do
|
|
21
23
|
def web(request, response)
|
22
24
|
end
|
23
25
|
|
26
|
+
def greet(payload)
|
27
|
+
end
|
28
|
+
|
24
29
|
def self.name
|
25
30
|
"Lita::Handlers::Test"
|
26
31
|
end
|
@@ -36,6 +41,9 @@ describe handler_class, lita_handler: true do
|
|
36
41
|
it { routes("restricted").to(:restricted) }
|
37
42
|
it { routes_http(:get, "web").to(:web) }
|
38
43
|
it { doesnt_route_http(:post, "web").to(:web) }
|
44
|
+
it { routes_event(:connected).to(:greet) }
|
45
|
+
it { doesnt_route_event(:connected).to(:web) }
|
46
|
+
it { does_not_route_event(:connected).to(:web) }
|
39
47
|
|
40
48
|
describe "#foo" do
|
41
49
|
it "replies with baz" do
|
data/spec/lita/source_spec.rb
CHANGED
@@ -2,12 +2,43 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Lita::Source do
|
4
4
|
it "has a user" do
|
5
|
-
subject = described_class.new("Carl")
|
5
|
+
subject = described_class.new(user: "Carl")
|
6
6
|
expect(subject.user).to eq("Carl")
|
7
7
|
end
|
8
8
|
|
9
9
|
it "has a room" do
|
10
|
-
subject = described_class.new(
|
10
|
+
subject = described_class.new(room: "#litabot")
|
11
11
|
expect(subject.room).to eq("#litabot")
|
12
12
|
end
|
13
|
+
|
14
|
+
it "has a private message flag" do
|
15
|
+
subject = described_class.new(user: "Carl", private_message: true)
|
16
|
+
expect(subject).to be_a_private_message
|
17
|
+
end
|
18
|
+
|
19
|
+
it "can be manually marked as private" do
|
20
|
+
subject = described_class.new(user: "Carl", room: "#litabot")
|
21
|
+
subject.private_message!
|
22
|
+
expect(subject).to be_a_private_message
|
23
|
+
end
|
24
|
+
|
25
|
+
it "requires either a user or a room" do
|
26
|
+
expect { described_class.new }.to raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "the deprecated Source.new(user, room) API" do
|
30
|
+
it "can have a user and is marked as private if there is no room" do
|
31
|
+
expect(Lita.logger).to receive(:warn)
|
32
|
+
subject = described_class.new("Carl")
|
33
|
+
expect(subject.user).to eq("Carl")
|
34
|
+
expect(subject).to be_a_private_message
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can have a room and is not marked as private if it does" do
|
38
|
+
expect(Lita.logger).to receive(:warn)
|
39
|
+
subject = described_class.new("Carl", "#litabot")
|
40
|
+
expect(subject.room).to eq("#litabot")
|
41
|
+
expect(subject).not_to be_a_private_message
|
42
|
+
end
|
43
|
+
end
|
13
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lita
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jimmy Cuadra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -283,7 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
283
283
|
version: '0'
|
284
284
|
requirements: []
|
285
285
|
rubyforge_project:
|
286
|
-
rubygems_version: 2.
|
286
|
+
rubygems_version: 2.1.3
|
287
287
|
signing_key:
|
288
288
|
specification_version: 4
|
289
289
|
summary: A multi-service chat bot with extendable behavior.
|