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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04046c9229b2303b99d39582d60790888db1e611
4
- data.tar.gz: 0060005dadcb7608aa33051ed9571455463c3698
3
+ metadata.gz: a0f46a0926eb20ff35d1597e8d7474e64984ffd4
4
+ data.tar.gz: 63b751e98f2e477e41b144da5c731160963d2377
5
5
  SHA512:
6
- metadata.gz: 80caca833d509b65a8015de4f3e5845fc5c0c485f4b02b4d9ce70f3beb351f8cbc05b0bdbcac474be0e3248e53915e459e6f30068becbdb701bbe73ba7df295e
7
- data.tar.gz: 2c5d02ce8eed3c643dd9e0ef43b0467443ea5382686d36c785d9ebbf319ed0b4583c4d92ae1bec0036d49993c28a464aaf4aa3ae6cec1f55b6005bea1e7821b6
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 both chat routes and HTTP routes available to handlers.
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 handler 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(obj).to receive(:message)` syntax.
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 handlers
345
+ ### Testing adapters
324
346
 
325
- 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.
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::Handlers::MyHandler, lita_handler: true do
352
+ describe Lita::Adapters::MyAdapter, lita: true do
331
353
  # ...
332
354
  end
333
355
  ```
334
356
 
335
- This provides the following:
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.
@@ -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} > "
@@ -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.
@@ -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
- @robot.send_messages(Source.new(source.user), *strings)
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
@@ -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.
@@ -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
@@ -1,11 +1,16 @@
1
1
  module Lita
2
- # A wrapper object representing the source of an incoming message (the user
3
- # who sent it, and optionally the room they sent it from). If a room is set,
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. Source objects are also used as "target"
6
- # objects when sending an outgoing message or performing another operation
7
- # on a user or a room.
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
- def initialize(user, room = nil)
24
- @user = user
25
- @room = room
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
@@ -1,4 +1,4 @@
1
1
  module Lita
2
2
  # The current version of Lita.
3
- VERSION = "2.4.0"
3
+ VERSION = "2.5.0"
4
4
  end
@@ -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
@@ -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)
@@ -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.room).to be_nil
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")
@@ -9,15 +9,28 @@ describe Lita::Robot do
9
9
  expect { subject }.to raise_error(SystemExit)
10
10
  end
11
11
 
12
- describe "#receive" do
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
- it "dispatches messages to every registered handler" do
16
+ before do
17
17
  allow(Lita).to receive(:handlers).and_return([handler1, handler2])
18
- expect(handler1).to receive(:dispatch).with(subject, "foo")
19
- expect(handler2).to receive(:dispatch).with(subject, "foo")
20
- subject.receive("foo")
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
 
@@ -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
@@ -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("Carl", "#litabot")
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.0
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-09-10 00:00:00.000000000 Z
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.0.3
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.