lita 4.5.0 → 4.6.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: b05600a1b35088abb38dbb5f4bf68e3f97f3758e
4
- data.tar.gz: d67724a6e50664c074e71729ca0cda9a389fcaa6
3
+ metadata.gz: 411c330d69cc62203d31374e506722511a8582aa
4
+ data.tar.gz: 36b57d4429140175ab4baa79a322dc13beac79c0
5
5
  SHA512:
6
- metadata.gz: 425041c5ed45f464f8374053f45f85ce0487cba75c6eb5c35e2ae54fbcb48891cae4fc21d5c8732da2984da626c639b1704cd72d74860892837e526241aed7a3
7
- data.tar.gz: 38658b9c6a4bc97c54f79355b49c36e1cb4a6329077554320f4376ed4170d4db3e84763178d989bbb8b7a6999f44425c653a55a27b4f9e564915183b74bbfb71
6
+ metadata.gz: 287c23415f235842e613290b117557624affe4e1357430e873128066f719d6a7d79fd1847a52a97c30b91d40d8a7a1cf6287c2044a05f619749d023bee55fd78
7
+ data.tar.gz: 4a44d63d33e8420f474a48ef63311f4f324f272da4dedf60399e86ee3f69b7a1c9f29d61adb092a18759e1b1341ede9fe31b57026666d1f118668e138fbe3b5e
@@ -115,6 +115,7 @@ require_relative "lita/timer"
115
115
  require_relative "lita/robot"
116
116
  require_relative "lita/adapter"
117
117
  require_relative "lita/adapters/shell"
118
+ require_relative "lita/adapters/test"
118
119
  require_relative "lita/plugin_builder"
119
120
  require_relative "lita/route_validator"
120
121
  require_relative "lita/handlers/authorization"
@@ -4,6 +4,7 @@ module Lita
4
4
  # The names of methods that should be implemented by an adapter.
5
5
  # @since 4.4.0
6
6
  REQUIRED_METHODS = %i(
7
+ chat_service
7
8
  join
8
9
  part
9
10
  roster
@@ -65,6 +66,12 @@ module Lita
65
66
  robot.config.adapters.public_send(self.class.namespace)
66
67
  end
67
68
 
69
+ # @!method chat_service
70
+ # May return an object exposing chat-service-specific APIs.
71
+ # @return [Object, nil] The chat service API object, if any.
72
+ # @abstract This should be implemented by the adapter.
73
+ # @since 4.6.0
74
+
68
75
  # @!method join(room_id)
69
76
  # Joins the room with the specified ID.
70
77
  # @param room_id [String] The ID of the room.
@@ -0,0 +1,43 @@
1
+ module Lita
2
+ # A namespace to hold all subclasses of {Adapter}.
3
+ module Adapters
4
+ # An adapter for testing Lita and Lita plugins.
5
+ # @since 4.6.0
6
+ class Test < Adapter
7
+ # Adapter-specific methods exposed through {Robot}.
8
+ class ChatService
9
+ def initialize(sent_messages)
10
+ @sent_messages = sent_messages
11
+ end
12
+
13
+ # An array of recorded outgoing messages.
14
+ def sent_messages
15
+ @sent_messages.dup
16
+ end
17
+ end
18
+
19
+ def initialize(robot)
20
+ super
21
+
22
+ self.sent_messages = []
23
+ end
24
+
25
+ # Adapter-specific methods available via {Robot#chat_service}.
26
+ def chat_service
27
+ ChatService.new(sent_messages)
28
+ end
29
+
30
+ # Records outgoing messages.
31
+ def send_messages(_target, strings)
32
+ sent_messages.concat(strings)
33
+ end
34
+
35
+ private
36
+
37
+ # An array of recorded outgoing messages.
38
+ attr_accessor :sent_messages
39
+ end
40
+
41
+ Lita.register_adapter(:test, Test)
42
+ end
43
+ end
@@ -95,10 +95,8 @@ module Lita
95
95
  robot.hooks[:trigger_route].each { |hook| hook.call(response: response, route: route) }
96
96
  handler = new(robot)
97
97
  route.callback.call(handler, response)
98
- rescue Exception => e
99
- log_dispatch_error(e)
100
- robot.config.robot.error_handler.call(e)
101
- raise e if Lita.test_mode?
98
+ rescue => error
99
+ log_error(robot, error)
102
100
  end
103
101
 
104
102
  private
@@ -125,16 +123,6 @@ module Lita
125
123
  method: route.callback.method_name || "(block)"
126
124
  )
127
125
  end
128
-
129
- # Logs an error encountered during dispatch.
130
- def log_dispatch_error(e)
131
- Lita.logger.error I18n.t(
132
- "lita.handler.exception",
133
- handler: name,
134
- message: e.message,
135
- backtrace: e.backtrace.join("\n")
136
- )
137
- end
138
126
  end
139
127
  end
140
128
  end
@@ -37,6 +37,18 @@ module Lita
37
37
  end
38
38
 
39
39
  alias_method :t, :translate
40
+
41
+ # Logs an error raised by a plugin.
42
+ def log_error(robot, error)
43
+ robot.config.robot.error_handler.call(error)
44
+ Lita.logger.error I18n.t(
45
+ "lita.handler.exception",
46
+ handler: name,
47
+ message: error.message,
48
+ backtrace: error.backtrace.join("\n")
49
+ )
50
+ raise error if Lita.test_mode?
51
+ end
40
52
  end
41
53
 
42
54
  # A Redis::Namespace scoped to the handler.
@@ -57,7 +57,11 @@ module Lita
57
57
  # @return [Boolean] Whether or not the event triggered any callbacks.
58
58
  def trigger(robot, event_name, payload = {})
59
59
  event_subscriptions_for(event_name).map do |callback|
60
- callback.call(new(robot), payload)
60
+ begin
61
+ callback.call(new(robot), payload)
62
+ rescue => error
63
+ log_error(robot, error)
64
+ end
61
65
  end.any?
62
66
  end
63
67
 
@@ -36,13 +36,16 @@ module Lita
36
36
 
37
37
  def_delegators :registry, :config, :adapters, :handlers, :hooks
38
38
 
39
+ # @!method chat_service
40
+ # @see Lita::Adapter#chat_service
41
+ # @since 4.6.0
39
42
  # @!method mention_format(name)
40
43
  # @see Lita::Adapter#mention_format
41
44
  # @since 4.4.0
42
45
  # @!method roster(room)
43
46
  # @see Lita::Adapter#roster
44
47
  # @since 4.4.1
45
- def_delegators :adapter, :mention_format, :roster
48
+ def_delegators :adapter, :chat_service, :mention_format, :roster
46
49
 
47
50
  # @param registry [Lita::Registry] The registry for the robot's configuration and plugins.
48
51
  def initialize(registry = Lita)
@@ -18,13 +18,27 @@ module Lita
18
18
  base.send(:include, Lita::RSpec)
19
19
 
20
20
  prepare_handlers(base)
21
+ prepare_adapter(base)
21
22
  prepare_let_blocks(base)
22
23
  prepare_subject(base)
23
- prepare_robot(base)
24
24
  end
25
25
 
26
26
  private
27
27
 
28
+ # Stub Lita.adapters
29
+ def prepare_adapter(base)
30
+ base.class_eval do
31
+ before do
32
+ if Lita.version_3_compatibility_mode?
33
+ Lita.config.robot.adapter = :test
34
+ else
35
+ registry.register_adapter(:test, Lita::Adapters::Test)
36
+ registry.config.robot.adapter = :test
37
+ end
38
+ end
39
+ end
40
+ end
41
+
28
42
  # Stub Lita.handlers.
29
43
  def prepare_handlers(base)
30
44
  base.class_eval do
@@ -50,20 +64,7 @@ module Lita
50
64
  let(:robot) { Robot.new(registry) }
51
65
  let(:source) { Source.new(user: user) }
52
66
  let(:user) { User.create("1", name: "Test User") }
53
- let(:replies) { [] }
54
- end
55
- end
56
-
57
- # Stub Lita::Robot#send_messages.
58
- def prepare_robot(base)
59
- base.class_eval do
60
- before do
61
- [:send_messages, :send_message].each do |message|
62
- allow(robot).to receive(message) do |_target, *strings|
63
- replies.concat(strings)
64
- end
65
- end
66
- end
67
+ let(:replies) { robot.chat_service.sent_messages }
67
68
  end
68
69
  end
69
70
 
@@ -71,7 +72,6 @@ module Lita
71
72
  def prepare_subject(base)
72
73
  base.class_eval do
73
74
  subject { described_class.new(robot) }
74
- before { allow(described_class).to receive(:new).and_return(subject) }
75
75
  end
76
76
  end
77
77
  end
@@ -81,8 +81,12 @@ module Lita
81
81
  # @param as [Lita::User] The user sending the message.
82
82
  # @param from [Lita::Room] The room where the message is received from.
83
83
  # @return [void]
84
- def send_message(body, as: user, from: nil)
85
- message = Message.new(robot, body, Source.new(user: as, room: from))
84
+ def send_message(body, as: user, from: nil, privately: false)
85
+ message = Message.new(
86
+ robot,
87
+ body,
88
+ Source.new(user: as, room: from, private_message: privately)
89
+ )
86
90
 
87
91
  robot.receive(message)
88
92
  end
@@ -92,8 +96,8 @@ module Lita
92
96
  # @param as [Lita::User] The user sending the message.
93
97
  # @param from [Lita::Room] The room where the message is received from.
94
98
  # @return [void]
95
- def send_command(body, as: user, from: nil)
96
- send_message("#{robot.mention_name}: #{body}", as: as, from: from)
99
+ def send_command(body, as: user, from: nil, privately: false)
100
+ send_message("#{robot.mention_name}: #{body}", as: as, from: from, privately: privately)
97
101
  end
98
102
 
99
103
  # Returns a Faraday connection hooked up to the currently running robot's Rack app.
@@ -1,4 +1,4 @@
1
1
  module Lita
2
2
  # The current version of Lita.
3
- VERSION = "4.5.0"
3
+ VERSION = "4.6.0"
4
4
  end
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Lita::Handler::EventRouter do
4
- let(:robot) { instance_double("Lita::Robot", name: "Lita") }
3
+ describe Lita::Handler::EventRouter, lita: true do
4
+ let(:robot) { Lita::Robot.new(registry) }
5
5
 
6
6
  subject do
7
7
  Class.new do
@@ -27,6 +27,16 @@ describe Lita::Handler::EventRouter do
27
27
 
28
28
  on(:multiple_callbacks) { robot.send_message("first callback") }
29
29
  on(:multiple_callbacks) { robot.send_message("second callback") }
30
+
31
+ on(:multiple_errors) do
32
+ robot.send_message("first error")
33
+ raise ArgumentError, "first"
34
+ end
35
+
36
+ on(:multiple_errors) do
37
+ robot.send_message("second error")
38
+ raise ArgumentError, "second"
39
+ end
30
40
  end
31
41
  end
32
42
 
@@ -61,5 +71,47 @@ describe Lita::Handler::EventRouter do
61
71
  subject.trigger(robot, "connected")
62
72
  subject.trigger(robot, " ConNected ")
63
73
  end
74
+
75
+ context "not in test mode" do
76
+ around do |example|
77
+ test_mode = Lita.test_mode?
78
+ Lita.test_mode = false
79
+ begin
80
+ example.run
81
+ ensure
82
+ Lita.test_mode = test_mode
83
+ end
84
+ end
85
+
86
+ it "doesn't stop triggering callbacks after an exception is raised" do
87
+ expect(robot).to receive(:send_message).with("first error").once
88
+ expect(robot).to receive(:send_message).with("second error").once
89
+ subject.trigger(robot, :multiple_errors)
90
+ end
91
+
92
+ it "reports callback exceptions to the error handler" do
93
+ allow(robot).to receive(:send_message)
94
+ expect(registry.config.robot.error_handler).to receive(:call).twice
95
+ subject.trigger(robot, :multiple_errors)
96
+ end
97
+ end
98
+
99
+ context "in test mode" do
100
+ around do |example|
101
+ test_mode = Lita.test_mode?
102
+ Lita.test_mode = true
103
+ begin
104
+ example.run
105
+ ensure
106
+ Lita.test_mode = test_mode
107
+ end
108
+ end
109
+
110
+ it "re-raises callback exceptions immediately" do
111
+ allow(robot).to receive(:send_message)
112
+ expect(registry.config.robot.error_handler).to receive(:call).once
113
+ expect { subject.trigger(robot, :multiple_errors) }.to raise_error(ArgumentError, "first")
114
+ end
115
+ end
64
116
  end
65
117
  end
@@ -39,7 +39,7 @@ describe Lita::Handlers::Info, lita_handler: true do
39
39
 
40
40
  it "includes the adapter being used" do
41
41
  subject.web(request, response)
42
- expect(json).to include("adapter" => Lita.config.robot.adapter.to_s)
42
+ expect(json).to include("adapter" => registry.config.robot.adapter.to_s)
43
43
  end
44
44
 
45
45
  it "includes the robot's name" do
@@ -44,6 +44,10 @@ describe Lita::Robot, lita: true do
44
44
  subject.roster(instance_double("Lita::Room"))
45
45
  end
46
46
 
47
+ it "exposes Adapter#chat_service" do
48
+ expect { subject.chat_service }.not_to raise_error
49
+ end
50
+
47
51
  context "with registered handlers" do
48
52
  let(:handler1) { Class.new(Lita::Handler) { namespace :test } }
49
53
  let(:handler2) { Class.new(Lita::Handler) { namespace :test } }
@@ -3,6 +3,7 @@ require "spec_helper"
3
3
  handler_class = Class.new(Lita::Handler) do
4
4
  route(/^message$/, :message)
5
5
  route(/^channel$/, :channel)
6
+ route(/^private message$/, :private_message)
6
7
  route(/^command$/, :command, command: true)
7
8
  route("restricted", :restricted, restrict_to: :some_group)
8
9
  route("admins only", :admins_only, restrict_to: :admins)
@@ -24,6 +25,14 @@ handler_class = Class.new(Lita::Handler) do
24
25
  end
25
26
  end
26
27
 
28
+ def private_message(response)
29
+ if response.private_message?
30
+ response.reply("Private")
31
+ else
32
+ response.reply("Public")
33
+ end
34
+ end
35
+
27
36
  def command(response)
28
37
  response.reply("a", "command")
29
38
  end
@@ -116,12 +125,40 @@ describe handler_class, lita_handler: true do
116
125
  send_message("channel", from: room)
117
126
  expect(replies).to eq(%w(1 Room))
118
127
  end
128
+
119
129
  it "replies with no channel if not sent from room" do
120
130
  send_message("channel")
121
131
  expect(replies).to eq(["No room"])
122
132
  end
123
133
  end
124
134
 
135
+ describe "#private_message" do
136
+ let(:another_user) do
137
+ Lita::User.create(2, name: "Another User")
138
+ end
139
+
140
+ let(:room) do
141
+ Lita::Room.create_or_update(1, name: "Room")
142
+ end
143
+
144
+ it "replies with Private in response to a private message" do
145
+ send_message("private message", as: another_user, privately: true)
146
+ expect(source).to be_a_private_message
147
+ expect(replies.last).to eq("Private")
148
+ end
149
+
150
+ it "replies with Private in response to a private command" do
151
+ send_command("private message", as: another_user, privately: true)
152
+ expect(source).to be_a_private_message
153
+ expect(replies.last).to eq("Private")
154
+ end
155
+
156
+ it "replies with Public in response to a public message" do
157
+ send_message("private message", as: another_user, from: room)
158
+ expect(replies.last).to eq("Public")
159
+ end
160
+ end
161
+
125
162
  describe "#command" do
126
163
  it "replies with two strings" do
127
164
  send_command("command")
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: 4.5.0
4
+ version: 4.6.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: 2015-08-21 00:00:00.000000000 Z
11
+ date: 2015-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -282,6 +282,7 @@ files:
282
282
  - lib/lita.rb
283
283
  - lib/lita/adapter.rb
284
284
  - lib/lita/adapters/shell.rb
285
+ - lib/lita/adapters/test.rb
285
286
  - lib/lita/authorization.rb
286
287
  - lib/lita/callback.rb
287
288
  - lib/lita/cli.rb
@@ -449,3 +450,4 @@ test_files:
449
450
  - spec/templates/basic.irc.erb
450
451
  - spec/templates/helpers.erb
451
452
  - spec/templates/interpolated.erb
453
+ has_rdoc: