lita 4.4.3 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60f8a5c4baff97cb21c6bda0e37416b919747443
4
- data.tar.gz: 2ecdd16eb4c246c566178a31f4cfc277e0794282
3
+ metadata.gz: b05600a1b35088abb38dbb5f4bf68e3f97f3758e
4
+ data.tar.gz: d67724a6e50664c074e71729ca0cda9a389fcaa6
5
5
  SHA512:
6
- metadata.gz: 1f9d6e452648e187da436d3b9fbb248ff90243abc47ac671340df664f42b4c12c7d7fb832f169583cb485dd4adb44b554a79f4751f6ba011b6be6ed22fdc35d0
7
- data.tar.gz: 55d2096400b2dca088b16b40f07ae0888ed30ec98ad9dc6e873c5a2b7a23132b7b16c8649a3b61c49a1a0a6c9009c830bc0e7b5ce6f7c589aeef37c0b105eb57
6
+ metadata.gz: 425041c5ed45f464f8374053f45f85ce0487cba75c6eb5c35e2ae54fbcb48891cae4fc21d5c8732da2984da626c639b1704cd72d74860892837e526241aed7a3
7
+ data.tar.gz: 38658b9c6a4bc97c54f79355b49c36e1cb4a6329077554320f4376ed4170d4db3e84763178d989bbb8b7a6999f44425c653a55a27b4f9e564915183b74bbfb71
@@ -24,6 +24,8 @@ LineLength:
24
24
  Max: 100
25
25
  MethodLength:
26
26
  Enabled: false
27
+ NestedMethodDefinition:
28
+ Enabled: false
27
29
  NonNilCheck:
28
30
  Enabled: false
29
31
  ParameterLists:
@@ -1,9 +1,17 @@
1
1
  language: ruby
2
+ sudo: false
2
3
  cache: bundler
3
4
  rvm:
4
5
  - 2.0
5
6
  - 2.1
6
7
  - 2.2
8
+ - jruby-9.0.0.0
9
+ - rbx-2
10
+ matrix:
11
+ allow_failures:
12
+ - rvm: jruby-9.0.0.0
13
+ - rvm: rbx-2
14
+ fast_finish: true
7
15
  script: bundle exec rake
8
16
  before_install:
9
17
  - gem update --system
@@ -13,6 +21,7 @@ branches:
13
21
  except:
14
22
  - /^v[0-9]/
15
23
  notifications:
24
+ email: false
16
25
  webhooks:
17
26
  urls:
18
27
  - https://lita-freenode.herokuapp.com/travis
@@ -9,7 +9,7 @@ module Lita
9
9
  end
10
10
 
11
11
  # A Struct representing a chat route defined by a handler.
12
- class Route < Struct.new(
12
+ Route = Struct.new(
13
13
  :pattern,
14
14
  :callback,
15
15
  :command,
@@ -17,6 +17,8 @@ module Lita
17
17
  :help,
18
18
  :extensions
19
19
  )
20
+
21
+ class Route
20
22
  alias_method :command?, :command
21
23
  end
22
24
 
@@ -70,6 +72,13 @@ module Lita
70
72
  routes.map do |route|
71
73
  next unless route_applies?(route, message, robot)
72
74
  log_dispatch(route)
75
+ robot.trigger(
76
+ :message_dispatched,
77
+ handler: self,
78
+ route: route,
79
+ message: message,
80
+ robot: robot
81
+ )
73
82
  dispatch_to_route(route, robot, message)
74
83
  true
75
84
  end.any?
@@ -104,10 +104,34 @@ module Lita
104
104
  Lita.logger
105
105
  end
106
106
 
107
+ # Render an ERB template to a string, with any provided variables made available to the
108
+ # template.
109
+ # @param template_name [String] The name of the ERB template file.
110
+ # @param variables [Hash] An optional hash of variables to make available within the
111
+ # template. Hash keys become instance variable names with the hash values as the instance
112
+ # variables' values.
113
+ # @return [String] The rendered template.
114
+ # @since 4.2.0
107
115
  def render_template(template_name, variables = {})
108
116
  Template.from_file(file_for_template(template_name)).render(variables)
109
117
  end
110
118
 
119
+ # Renders an ERB template to a string, like {#render_template}, but also takes an array of
120
+ # modules with helper methods to be made available to the template.
121
+ # @param template_name [String] The name of the ERB template file.
122
+ # @param helpers [Array<Module>] An array of modules whose methods should be added to the
123
+ # template evaluation context.
124
+ # @param variables [Hash] An optional hash of variables to make available within the
125
+ # template. Hash keys become instance variable names with the hash values as the instance
126
+ # variables' values.
127
+ # @return [String] The rendered template.
128
+ # @since 4.5.0
129
+ def render_template_with_helpers(template_name, helpers, variables = {})
130
+ template = Template.from_file(file_for_template(template_name))
131
+ helpers.each { |helper| template.add_helper(helper) }
132
+ template.render(variables)
133
+ end
134
+
111
135
  # @see .translate
112
136
  def translate(*args)
113
137
  self.class.translate(*args)
@@ -1,17 +1,3 @@
1
- # Primary class from the +http_router+ gem.
2
- # @todo Remove this monkey patch as soon as a gem is released with this pull request merged:
3
- # https://github.com/joshbuddy/http_router/pull/40
4
- class HttpRouter
5
- # An individual HTTP route.
6
- class Route
7
- # Sets a name for the route. Monkey patched due to a bug.
8
- def name=(name)
9
- @name = name
10
- router.named_routes[name] << self if router
11
- end
12
- end
13
- end
14
-
15
1
  module Lita
16
2
  # Handlers use this class to define HTTP routes for the built-in web
17
3
  # server.
@@ -12,10 +12,20 @@ module Lita
12
12
  attr_reader :source
13
13
 
14
14
  # @!method user
15
- # The user who sent the message.
16
- # @return [Lita::User] The user.
17
- # @see Lita::Source#user
18
- def_delegators :source, :user
15
+ # The user who sent the message.
16
+ # @return [Lita::User] The user.
17
+ # @see Lita::Source#user
18
+ # @!method room_object
19
+ # The room where the message came from.
20
+ # @return [Lita::Room] The room.
21
+ # @see Lita::Source#room_object
22
+ # @since 4.5.0
23
+ # @!method private_message?
24
+ # Flag indicating that the message was sent to the robot privately.
25
+ # @return [Boolean] The boolean flag.
26
+ # @see Lita::Source#private_message?
27
+ # @since 4.5.0
28
+ def_delegators :source, :user, :room_object, :private_message?
19
29
 
20
30
  # @param robot [Lita::Robot] The currently running robot.
21
31
  # @param body [String] The body of the message.
@@ -25,10 +35,15 @@ module Lita
25
35
  @body = body
26
36
  @source = source
27
37
 
28
- name_pattern = Regexp.escape(@robot.mention_name)
29
- name_pattern = "#{name_pattern}|#{Regexp.escape(@robot.alias)}" if @robot.alias
38
+ name_pattern = "@?#{Regexp.escape(@robot.mention_name)}[:,]?\\s+"
39
+ alias_pattern = "#{Regexp.escape(@robot.alias)}\\s*" if @robot.alias
40
+ command_regex = if alias_pattern
41
+ /^\s*(?:#{name_pattern}|#{alias_pattern})/i
42
+ else
43
+ /^\s*#{name_pattern}/i
44
+ end
30
45
 
31
- @command = !!@body.sub!(/^\s*@?(?:#{name_pattern})[:,]?\s*/i, "")
46
+ @command = !!@body.sub!(command_regex, "")
32
47
  end
33
48
 
34
49
  # An array of arguments created by shellsplitting the message body, as if
@@ -4,7 +4,7 @@ module Lita
4
4
  # @api private
5
5
  class MiddlewareRegistry
6
6
  # A Rack middleware and its initialization arguments.
7
- class MiddlewareWrapper < Struct.new(:middleware, :args, :block); end
7
+ MiddlewareWrapper = Struct.new(:middleware, :args, :block)
8
8
 
9
9
  extend Forwardable
10
10
 
@@ -42,6 +42,12 @@ module Lita
42
42
  router.call(env)
43
43
  end
44
44
 
45
+ # Overrides the default inspect implementation to make output less verbose and more readable.
46
+ def inspect
47
+ hex_address = (object_id << 1).to_s(16).rjust(14, "0")
48
+ "#<Lita::RackApp:0x#{hex_address}>"
49
+ end
50
+
45
51
  # Finds the first route that matches the request environment, if any. Does not trigger the
46
52
  # route.
47
53
  # @param env [Hash] A Rack environment.
@@ -27,8 +27,16 @@ module Lita
27
27
  # @see Lita::Message#reply_with_mention
28
28
  # @!method user
29
29
  # @see Lita::Message#user
30
+ # @!method private_message?
31
+ # @see Lita::Message#private_message?
32
+ # @since 4.5.0
30
33
  def_delegators :message, :args, :reply, :reply_privately,
31
- :reply_with_mention, :user, :command?
34
+ :reply_with_mention, :user, :private_message?, :command?
35
+
36
+ # @!method room
37
+ # @see Lita::Message#room_object
38
+ # @since 4.5.0
39
+ def_delegator :message, :room_object, :room
32
40
 
33
41
  # @param message [Lita::Message] The incoming message.
34
42
  # @param pattern [Regexp] The pattern the incoming message matched.
@@ -31,7 +31,15 @@ module Lita
31
31
  return unless command_satisfied?(route, message)
32
32
  return if from_self?(message, robot)
33
33
  return unless matches_pattern?(route, message)
34
- return unless authorized?(robot, message.user, route.required_groups)
34
+ unless authorized?(robot, message.user, route.required_groups)
35
+ robot.trigger(
36
+ :route_authorization_failed,
37
+ message: message,
38
+ robot: robot,
39
+ route: route,
40
+ )
41
+ return
42
+ end
35
43
  return unless passes_route_hooks?(route, message, robot)
36
44
 
37
45
  true
@@ -10,6 +10,7 @@ module Lita
10
10
  include Matchers::ChatRouteMatcher
11
11
  include Matchers::HTTPRouteMatcher
12
12
  include Matchers::EventRouteMatcher
13
+ include Matchers::DeprecatedMethods
13
14
 
14
15
  class << self
15
16
  # Sets up the RSpec environment to easily test Lita handlers.
@@ -78,13 +79,10 @@ module Lita
78
79
  # Sends a message to the robot.
79
80
  # @param body [String] The message to send.
80
81
  # @param as [Lita::User] The user sending the message.
82
+ # @param from [Lita::Room] The room where the message is received from.
81
83
  # @return [void]
82
- def send_message(body, as: user)
83
- message = if as == user
84
- Message.new(robot, body, source)
85
- else
86
- Message.new(robot, body, Source.new(user: as))
87
- end
84
+ def send_message(body, as: user, from: nil)
85
+ message = Message.new(robot, body, Source.new(user: as, room: from))
88
86
 
89
87
  robot.receive(message)
90
88
  end
@@ -92,9 +90,10 @@ module Lita
92
90
  # Sends a "command" message to the robot.
93
91
  # @param body [String] The message to send.
94
92
  # @param as [Lita::User] The user sending the message.
93
+ # @param from [Lita::Room] The room where the message is received from.
95
94
  # @return [void]
96
- def send_command(body, as: user)
97
- send_message("#{robot.mention_name}: #{body}", as: as)
95
+ def send_command(body, as: user, from: nil)
96
+ send_message("#{robot.mention_name}: #{body}", as: as, from: from)
98
97
  end
99
98
 
100
99
  # Returns a Faraday connection hooked up to the currently running robot's Rack app.
@@ -109,138 +108,6 @@ module Lita
109
108
 
110
109
  Faraday::Connection.new { |c| c.adapter(:rack, robot.app) }
111
110
  end
112
-
113
- # Starts a chat routing test chain, asserting that a message should
114
- # trigger a route.
115
- # @param message [String] The message that should trigger the route.
116
- # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should have +to+
117
- # called on it to complete the test.
118
- # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route+ instead.
119
- def routes(message)
120
- STDERR.puts I18n.t(
121
- "lita.rspec.matcher_deprecated",
122
- old_method: "routes",
123
- new_method: "is_expected.to route",
124
- )
125
- Matchers::Deprecated.new(self, :route, true, message)
126
- end
127
-
128
- # Starts a chat routing test chain, asserting that a message should not
129
- # trigger a route.
130
- # @param message [String] The message that should not trigger the route.
131
- # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should have +to+
132
- # called on it to complete the test.
133
- # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route+ instead.
134
- def does_not_route(message)
135
- STDERR.puts I18n.t(
136
- "lita.rspec.matcher_deprecated",
137
- old_method: "does_not_route",
138
- new_method: "is_expected.not_to route",
139
- )
140
- Matchers::Deprecated.new(self, :route, false, message)
141
- end
142
- alias_method :doesnt_route, :does_not_route
143
-
144
- # Starts a chat routing test chain, asserting that a "command" message
145
- # should trigger a route.
146
- # @param message [String] The message that should trigger the route.
147
- # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should have +to+
148
- # called on it to complete the test.
149
- # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route_command+ instead.
150
- def routes_command(message)
151
- STDERR.puts I18n.t(
152
- "lita.rspec.matcher_deprecated",
153
- old_method: "routes_command",
154
- new_method: "is_expected.to route_command",
155
- )
156
- Matchers::Deprecated.new(self, :route_command, true, message)
157
- end
158
-
159
- # Starts a chat routing test chain, asserting that a "command" message
160
- # should not trigger a route.
161
- # @param message [String] The message that should not trigger the route.
162
- # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should have +to+
163
- # called on it to complete the test.
164
- # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route_command+ instead.
165
- def does_not_route_command(message)
166
- STDERR.puts I18n.t(
167
- "lita.rspec.matcher_deprecated",
168
- old_method: "does_not_route_command",
169
- new_method: "is_expected.not_to route_command",
170
- )
171
- Matchers::Deprecated.new(self, :route_command, false, message)
172
- end
173
- alias_method :doesnt_route_command, :does_not_route_command
174
-
175
- # Starts an HTTP routing test chain, asserting that a request to the given
176
- # path with the given HTTP request method will trigger a route.
177
- # @param http_method [Symbol] The HTTP request method that should trigger
178
- # the route.
179
- # @param path [String] The path URL component that should trigger the
180
- # route.
181
- # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should
182
- # have +to+ called on it to complete the test.
183
- # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route_http+ instead.
184
- def routes_http(http_method, path)
185
- STDERR.puts I18n.t(
186
- "lita.rspec.matcher_deprecated",
187
- old_method: "routes_http",
188
- new_method: "is_expected.to route_http",
189
- )
190
- Matchers::Deprecated.new(self, :route_http, true, http_method, path)
191
- end
192
-
193
- # Starts an HTTP routing test chain, asserting that a request to the given
194
- # path with the given HTTP request method will not trigger a route.
195
- # @param http_method [Symbol] The HTTP request method that should not
196
- # trigger the route.
197
- # @param path [String] The path URL component that should not trigger the
198
- # route.
199
- # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should
200
- # have +to+ called on it to complete the test.
201
- # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route_http+ instead.
202
- def does_not_route_http(http_method, path)
203
- STDERR.puts I18n.t(
204
- "lita.rspec.matcher_deprecated",
205
- old_method: "does_not_route_http",
206
- new_method: "is_expected.not_to route_http",
207
- )
208
- Matchers::Deprecated.new(self, :route_http, false, http_method, path)
209
- end
210
- alias_method :doesnt_route_http, :does_not_route_http
211
-
212
- # Starts an event subscription test chain, asserting that an event should
213
- # trigger the target method.
214
- # @param event_name [String, Symbol] The name of the event that should
215
- # be triggered.
216
- # @return [Matchers::Deprecated] A {Matchers::Deprecated} that
217
- # should have +to+ called on it to complete the test.
218
- # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route_event+ instead.
219
- def routes_event(event_name)
220
- STDERR.puts I18n.t(
221
- "lita.rspec.matcher_deprecated",
222
- old_method: "routes_event",
223
- new_method: "is_expected.to route_event",
224
- )
225
- Matchers::Deprecated.new(self, :route_event, true, event_name)
226
- end
227
-
228
- # Starts an event subscription test chain, asserting that an event should
229
- # not trigger the target method.
230
- # @param event_name [String, Symbol] The name of the event that should
231
- # not be triggered.
232
- # @return [Matchers::Deprecated] A {Matchers::Deprecated} that
233
- # should have +to+ called on it to complete the test.
234
- # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route_event+ instead.
235
- def does_not_route_event(event_name)
236
- STDERR.puts I18n.t(
237
- "lita.rspec.matcher_deprecated",
238
- old_method: "does_not_route_event",
239
- new_method: "is_expected.not_to route_event",
240
- )
241
- Matchers::Deprecated.new(self, :route_event, false, event_name)
242
- end
243
- alias_method :doesnt_route_event, :does_not_route_event
244
111
  end
245
112
  end
246
113
  end
@@ -1,6 +1,140 @@
1
1
  module Lita
2
2
  module RSpec
3
3
  module Matchers
4
+ module DeprecatedMethods
5
+ # Starts a chat routing test chain, asserting that a message should
6
+ # trigger a route.
7
+ # @param message [String] The message that should trigger the route.
8
+ # @return [Deprecated] A {Deprecated} that should have +to+
9
+ # called on it to complete the test.
10
+ # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route+ instead.
11
+ def routes(message)
12
+ STDERR.puts I18n.t(
13
+ "lita.rspec.matcher_deprecated",
14
+ old_method: "routes",
15
+ new_method: "is_expected.to route",
16
+ )
17
+ Deprecated.new(self, :route, true, message)
18
+ end
19
+
20
+ # Starts a chat routing test chain, asserting that a message should not
21
+ # trigger a route.
22
+ # @param message [String] The message that should not trigger the route.
23
+ # @return [Deprecated] A {Deprecated} that should have +to+
24
+ # called on it to complete the test.
25
+ # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route+ instead.
26
+ def does_not_route(message)
27
+ STDERR.puts I18n.t(
28
+ "lita.rspec.matcher_deprecated",
29
+ old_method: "does_not_route",
30
+ new_method: "is_expected.not_to route",
31
+ )
32
+ Deprecated.new(self, :route, false, message)
33
+ end
34
+ alias_method :doesnt_route, :does_not_route
35
+
36
+ # Starts a chat routing test chain, asserting that a "command" message
37
+ # should trigger a route.
38
+ # @param message [String] The message that should trigger the route.
39
+ # @return [Deprecated] A {Deprecated} that should have +to+
40
+ # called on it to complete the test.
41
+ # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route_command+ instead.
42
+ def routes_command(message)
43
+ STDERR.puts I18n.t(
44
+ "lita.rspec.matcher_deprecated",
45
+ old_method: "routes_command",
46
+ new_method: "is_expected.to route_command",
47
+ )
48
+ Deprecated.new(self, :route_command, true, message)
49
+ end
50
+
51
+ # Starts a chat routing test chain, asserting that a "command" message
52
+ # should not trigger a route.
53
+ # @param message [String] The message that should not trigger the route.
54
+ # @return [Deprecated] A {Deprecated} that should have +to+
55
+ # called on it to complete the test.
56
+ # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route_command+ instead.
57
+ def does_not_route_command(message)
58
+ STDERR.puts I18n.t(
59
+ "lita.rspec.matcher_deprecated",
60
+ old_method: "does_not_route_command",
61
+ new_method: "is_expected.not_to route_command",
62
+ )
63
+ Deprecated.new(self, :route_command, false, message)
64
+ end
65
+ alias_method :doesnt_route_command, :does_not_route_command
66
+
67
+ # Starts an HTTP routing test chain, asserting that a request to the given
68
+ # path with the given HTTP request method will trigger a route.
69
+ # @param http_method [Symbol] The HTTP request method that should trigger
70
+ # the route.
71
+ # @param path [String] The path URL component that should trigger the
72
+ # route.
73
+ # @return [Deprecated] A {Deprecated} that should
74
+ # have +to+ called on it to complete the test.
75
+ # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route_http+ instead.
76
+ def routes_http(http_method, path)
77
+ STDERR.puts I18n.t(
78
+ "lita.rspec.matcher_deprecated",
79
+ old_method: "routes_http",
80
+ new_method: "is_expected.to route_http",
81
+ )
82
+ Deprecated.new(self, :route_http, true, http_method, path)
83
+ end
84
+
85
+ # Starts an HTTP routing test chain, asserting that a request to the given
86
+ # path with the given HTTP request method will not trigger a route.
87
+ # @param http_method [Symbol] The HTTP request method that should not
88
+ # trigger the route.
89
+ # @param path [String] The path URL component that should not trigger the
90
+ # route.
91
+ # @return [Deprecated] A {Deprecated} that should
92
+ # have +to+ called on it to complete the test.
93
+ # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route_http+ instead.
94
+ def does_not_route_http(http_method, path)
95
+ STDERR.puts I18n.t(
96
+ "lita.rspec.matcher_deprecated",
97
+ old_method: "does_not_route_http",
98
+ new_method: "is_expected.not_to route_http",
99
+ )
100
+ Deprecated.new(self, :route_http, false, http_method, path)
101
+ end
102
+ alias_method :doesnt_route_http, :does_not_route_http
103
+
104
+ # Starts an event subscription test chain, asserting that an event should
105
+ # trigger the target method.
106
+ # @param event_name [String, Symbol] The name of the event that should
107
+ # be triggered.
108
+ # @return [Deprecated] A {Deprecated} that
109
+ # should have +to+ called on it to complete the test.
110
+ # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route_event+ instead.
111
+ def routes_event(event_name)
112
+ STDERR.puts I18n.t(
113
+ "lita.rspec.matcher_deprecated",
114
+ old_method: "routes_event",
115
+ new_method: "is_expected.to route_event",
116
+ )
117
+ Deprecated.new(self, :route_event, true, event_name)
118
+ end
119
+
120
+ # Starts an event subscription test chain, asserting that an event should
121
+ # not trigger the target method.
122
+ # @param event_name [String, Symbol] The name of the event that should
123
+ # not be triggered.
124
+ # @return [Deprecated] A {Deprecated} that
125
+ # should have +to+ called on it to complete the test.
126
+ # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route_event+ instead.
127
+ def does_not_route_event(event_name)
128
+ STDERR.puts I18n.t(
129
+ "lita.rspec.matcher_deprecated",
130
+ old_method: "does_not_route_event",
131
+ new_method: "is_expected.not_to route_event",
132
+ )
133
+ Deprecated.new(self, :route_event, false, event_name)
134
+ end
135
+ alias_method :doesnt_route_event, :does_not_route_event
136
+ end
137
+
4
138
  # Lita 3 versions of the routing matchers.
5
139
  # @deprecated Will be removed in Lita 5.0. Use the +is_expected+ forms instead.
6
140
  class Deprecated
@@ -24,6 +24,15 @@ module Lita
24
24
  # @param source [String] A string to use as the template's content.
25
25
  def initialize(source)
26
26
  @erb = ERB.new(source, $SAFE, "<>")
27
+ self.helpers = Set.new
28
+ end
29
+
30
+ # Add a module of helpers methods to be added to the template evalutation context.
31
+ # @param helper [Module] The module to extend onto the template evalutation context.
32
+ # @return [void]
33
+ # @since 4.5.0
34
+ def add_helper(helper)
35
+ helpers << helper
27
36
  end
28
37
 
29
38
  # Render the template with the provided variables.
@@ -36,10 +45,14 @@ module Lita
36
45
 
37
46
  private
38
47
 
48
+ attr_accessor :helpers
49
+
39
50
  # Create an empty object to use as the ERB context and set any provided variables in it.
40
51
  def context_binding(variables)
41
52
  context = TemplateEvaluationContext.new
42
53
 
54
+ helpers.each { |helper| context.extend(helper) }
55
+
43
56
  variables.each do |k, v|
44
57
  context.instance_variable_set("@#{k}", v)
45
58
  end
@@ -1,4 +1,4 @@
1
1
  module Lita
2
2
  # The current version of Lita.
3
- VERSION = "4.4.3"
3
+ VERSION = "4.5.0"
4
4
  end
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_runtime_dependency "bundler", ">= 1.3"
24
24
  spec.add_runtime_dependency "faraday", ">= 0.8.7"
25
- spec.add_runtime_dependency "http_router", ">= 0.11.1"
25
+ spec.add_runtime_dependency "http_router", ">= 0.11.2"
26
26
  spec.add_runtime_dependency "ice_nine", ">= 0.11.0"
27
27
  spec.add_runtime_dependency "i18n", ">= 0.6.9"
28
28
  spec.add_runtime_dependency "multi_json", ">= 1.7.7"
@@ -38,5 +38,5 @@ Gem::Specification.new do |spec|
38
38
  spec.add_development_dependency "simplecov"
39
39
  spec.add_development_dependency "coveralls"
40
40
  spec.add_development_dependency "pry"
41
- spec.add_development_dependency "rubocop", "~> 0.28.0"
41
+ spec.add_development_dependency "rubocop", "~> 0.33.0"
42
42
  end
@@ -81,6 +81,12 @@ describe handler, lita_handler: true do
81
81
  expect(replies).to be_empty
82
82
  end
83
83
 
84
+ it "triggers a :route_authorization_failed event when a user is not authorized" do
85
+ allow(robot).to receive(:trigger)
86
+ expect(robot).to receive(:trigger).with(:route_authorization_failed, anything)
87
+ send_message("admin")
88
+ end
89
+
84
90
  it "ignores messages from itself" do
85
91
  allow(user).to receive(:name).and_return(robot.name)
86
92
  send_message("message")
@@ -104,6 +110,11 @@ describe handler, lita_handler: true do
104
110
  end
105
111
  end
106
112
 
113
+ it "triggers a message_dispatched event" do
114
+ expect(robot).to receive(:trigger).with(:message_dispatched, anything)
115
+ send_message("message")
116
+ end
117
+
107
118
  it "raises exceptions in test mode" do
108
119
  expect { send_message("error") }.to raise_error(RuntimeError)
109
120
  end
@@ -181,8 +192,8 @@ describe handler, lita_handler: true do
181
192
 
182
193
  context "with another handler registered" do
183
194
  before do
184
- registry.register_handler(:test_2) do
185
- route(/three/) { |response| response.reply "got three" }
195
+ registry.register_handler(:test_2) do
196
+ route(/three/) { |response| response.reply "got three" }
186
197
  end
187
198
  end
188
199
 
@@ -80,7 +80,7 @@ describe Lita::Handler::Common, lita: true do
80
80
 
81
81
  it "raises an exception if the handler doesn't have a name to derive the namespace from" do
82
82
  handler = Class.new { include Lita::Handler::Common }
83
- expect { handler.namespace }.to raise_error
83
+ expect { handler.namespace }.to raise_error(RuntimeError, /must set a namespace/)
84
84
  end
85
85
  end
86
86
 
@@ -198,6 +198,29 @@ describe Lita::Handler::Common, lita: true do
198
198
  end
199
199
  end
200
200
 
201
+ describe "#render_template_with_helpers" do
202
+ before do
203
+ handler.template_root(File.expand_path(File.join("..", "..", "..", "templates"), __FILE__))
204
+ end
205
+
206
+ it "extends custom helpers into the template evaluation context" do
207
+ helpers = Module.new do
208
+ def reverse_name(first, last)
209
+ "#{last}, #{first}"
210
+ end
211
+ end
212
+
213
+ result = subject.render_template_with_helpers(
214
+ "helpers",
215
+ [helpers],
216
+ first: "Carl",
217
+ last: "Pug",
218
+ )
219
+
220
+ expect(result).to eq("Pug, Carl")
221
+ end
222
+ end
223
+
201
224
  describe "timer methods" do
202
225
  let(:queue) { Queue.new }
203
226
 
@@ -1,8 +1,10 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Lita::Message do
4
+ let(:mention_name) { "LitaBot" }
5
+
4
6
  let(:robot) do
5
- instance_double("Lita::Robot", name: "Lita", mention_name: "LitaBot", alias: ".")
7
+ instance_double("Lita::Robot", name: "Lita", mention_name: mention_name, alias: ".")
6
8
  end
7
9
 
8
10
  let(:source) { instance_double("Lita::Source") }
@@ -39,31 +41,66 @@ describe Lita::Message do
39
41
  end
40
42
 
41
43
  describe "#command?" do
42
- it "is true when the message is addressed to the Robot" do
43
- subject = described_class.new(
44
- robot,
45
- "#{robot.mention_name}: hello",
46
- source
47
- )
48
- expect(subject).to be_a_command
44
+ context "when the message is addressed to the robot" do
45
+ subject { described_class.new(robot, "#{robot.mention_name}: hello", source) }
46
+
47
+ it "is true" do
48
+ expect(subject).to be_a_command
49
+ end
49
50
  end
50
51
 
51
- it "is true when the Robot's name is capitalized differently" do
52
- subject = described_class.new(
53
- robot,
54
- "#{robot.mention_name.upcase}: hello",
55
- source
56
- )
57
- expect(subject).to be_a_command
52
+ context "when the message is addressed to the robot with different capitalization" do
53
+ subject { described_class.new(robot, "#{robot.mention_name.upcase}: hello", source) }
54
+
55
+ it "is true" do
56
+ expect(subject).to be_a_command
57
+ end
58
58
  end
59
59
 
60
- it "is true when the Robot's alias is used" do
61
- subject = described_class.new(
62
- robot,
63
- "#{robot.alias}hello",
64
- source
65
- )
66
- expect(subject).to be_a_command
60
+ context "when the message is addressed to the robot with a comma" do
61
+ subject { described_class.new(robot, "#{robot.mention_name.upcase}, hello", source) }
62
+
63
+ it "is true" do
64
+ expect(subject).to be_a_command
65
+ end
66
+ end
67
+
68
+ context "when the message is addressed to the robot with no trailing punctuation" do
69
+ subject { described_class.new(robot, "#{robot.mention_name.upcase} hello", source) }
70
+
71
+ it "is true" do
72
+ expect(subject).to be_a_command
73
+ end
74
+ end
75
+
76
+ context "when the message is addressed to the bot via alias with no space after it" do
77
+ subject { described_class.new(robot, "#{robot.alias}hello", source) }
78
+
79
+ it "is true" do
80
+ expect(subject).to be_a_command
81
+ end
82
+ end
83
+
84
+ context "when the message is addressed to the bot via alias with space after it" do
85
+ subject { described_class.new(robot, "#{robot.alias} hello", source) }
86
+
87
+ it "is true" do
88
+ expect(subject).to be_a_command
89
+ end
90
+ end
91
+
92
+ context "when the message incidentally starts with the mention name" do
93
+ let(:mention_name) { "sa" }
94
+
95
+ subject { described_class.new(robot, "salmon", source) }
96
+
97
+ it "is false" do
98
+ expect(subject).not_to be_a_command
99
+ end
100
+
101
+ it "does not affect the message body" do
102
+ expect(subject.body).to eq("salmon")
103
+ end
67
104
  end
68
105
 
69
106
  it "is false when the message is not addressed to the Robot" do
@@ -78,6 +115,20 @@ describe Lita::Message do
78
115
  end
79
116
  end
80
117
 
118
+ describe "#room_object" do
119
+ it "delegates to #source" do
120
+ expect(subject.source).to receive(:room_object)
121
+ subject.room_object
122
+ end
123
+ end
124
+
125
+ describe "#private_message?" do
126
+ it "delegates to #source" do
127
+ expect(subject.source).to receive(:private_message?)
128
+ subject.private_message?
129
+ end
130
+ end
131
+
81
132
  describe "#reply" do
82
133
  it "sends strings back to the source through the robot" do
83
134
  expect(robot).to receive(:send_messages).with(source, "foo", "bar")
@@ -36,4 +36,25 @@ describe Lita::Response do
36
36
  expect(subject.extensions[:foo]).to eq(:bar)
37
37
  end
38
38
  end
39
+
40
+ describe "#user" do
41
+ it "delegates to #message" do
42
+ expect(subject.message).to receive(:user)
43
+ subject.user
44
+ end
45
+ end
46
+
47
+ describe "#room" do
48
+ it "delegates to #message" do
49
+ expect(subject.message).to receive(:room_object)
50
+ subject.room
51
+ end
52
+ end
53
+
54
+ describe "#private_message?" do
55
+ it "delegates to #message" do
56
+ expect(subject.message).to receive(:private_message?)
57
+ subject.private_message?
58
+ end
59
+ end
39
60
  end
@@ -2,6 +2,7 @@ require "spec_helper"
2
2
 
3
3
  handler_class = Class.new(Lita::Handler) do
4
4
  route(/^message$/, :message)
5
+ route(/^channel$/, :channel)
5
6
  route(/^command$/, :command, command: true)
6
7
  route("restricted", :restricted, restrict_to: :some_group)
7
8
  route("admins only", :admins_only, restrict_to: :admins)
@@ -14,6 +15,15 @@ handler_class = Class.new(Lita::Handler) do
14
15
  response.reply(response.user.name)
15
16
  end
16
17
 
18
+ def channel(response)
19
+ if (room = response.message.source.room_object)
20
+ response.reply(room.id)
21
+ response.reply(room.name)
22
+ else
23
+ response.reply("No room")
24
+ end
25
+ end
26
+
17
27
  def command(response)
18
28
  response.reply("a", "command")
19
29
  end
@@ -39,6 +49,12 @@ describe handler_class, lita_handler: true do
39
49
  it { is_expected.not_to route("message").to(:not_a_message) }
40
50
  end
41
51
 
52
+ describe "routing channels" do
53
+ it { is_expected.to route("channel") }
54
+ it { is_expected.to route("channel").to(:channel) }
55
+ it { is_expected.not_to route("channel").to(:not_a_channel) }
56
+ end
57
+
42
58
  describe "routing commands" do
43
59
  it { is_expected.to route_command("command") }
44
60
  it { is_expected.not_to route("command") }
@@ -94,6 +110,18 @@ describe handler_class, lita_handler: true do
94
110
  end
95
111
  end
96
112
 
113
+ describe "#channel" do
114
+ it "replies with channel id if sent from room" do
115
+ room = Lita::Room.create_or_update(1, name: "Room")
116
+ send_message("channel", from: room)
117
+ expect(replies).to eq(%w(1 Room))
118
+ end
119
+ it "replies with no channel if not sent from room" do
120
+ send_message("channel")
121
+ expect(replies).to eq(["No room"])
122
+ end
123
+ end
124
+
97
125
  describe "#command" do
98
126
  it "replies with two strings" do
99
127
  send_command("command")
@@ -13,6 +13,23 @@ describe Lita::Template do
13
13
  end
14
14
  end
15
15
 
16
+ describe "#add_helper" do
17
+ subject { described_class.new("<%= reverse_name(@first, @last) %>") }
18
+ let(:helper) do
19
+ Module.new do
20
+ def reverse_name(first, last)
21
+ "#{last}, #{first}"
22
+ end
23
+ end
24
+ end
25
+
26
+ it "adds the helper to the evaluation context" do
27
+ subject.add_helper(helper)
28
+
29
+ expect(subject.render(first: "Carl", last: "Pug")).to eq("Pug, Carl")
30
+ end
31
+ end
32
+
16
33
  describe "#render" do
17
34
  context "with a static source template" do
18
35
  subject { described_class.new("Hello, Lita!") }
@@ -158,9 +158,9 @@ describe Lita do
158
158
 
159
159
  before do
160
160
  allow_any_instance_of(Lita::Robot).to receive(:run)
161
- allow(Lita::ConfigurationValidator).to receive(:new).with(described_class).and_return(
162
- validator
163
- )
161
+ allow(
162
+ Lita::ConfigurationValidator
163
+ ).to receive(:new).with(described_class).and_return(validator)
164
164
  end
165
165
 
166
166
  after { described_class.reset }
@@ -0,0 +1 @@
1
+ <%= reverse_name(@first, @last) %>
@@ -1,16 +1,17 @@
1
1
  module Lita
2
2
  module <%= config[:constant_namespace] %>
3
3
  class <%= config[:constant_name] %><% unless config[:plugin_type] == "extension" %> < <%= config[:plugin_type].capitalize %><% end %>
4
- end
4
+ # insert <%= config[:plugin_type] %> code here
5
5
 
6
- <%- if config[:plugin_type] == "adapter" -%>
7
- Lita.register_adapter(:<%= config[:name] %>, <%= config[:constant_name] %>)
8
- <%- elsif config[:plugin_type] == "handler" -%>
9
- Lita.register_handler(<%= config[:constant_name] %>)
10
- <%- else -%>
11
- # If your extension needs to register with a Lita hook, uncomment the
12
- # following line and change the hook name to the appropriate value:
13
- # Lita.register_hook(:hook_name, <%= config[:constant_name] %>)
14
- <%- end -%>
6
+ <%- if config[:plugin_type] == "adapter" -%>
7
+ Lita.register_adapter(:<%= config[:name] %>, self)
8
+ <%- elsif config[:plugin_type] == "handler" -%>
9
+ Lita.register_handler(self)
10
+ <%- else -%>
11
+ # If your extension needs to register with a Lita hook, uncomment the
12
+ # following line and change the hook name to the appropriate value:
13
+ # Lita.register_hook(:hook_name, self)
14
+ <%- end -%>
15
+ end
15
16
  end
16
17
  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: 4.4.3
4
+ version: 4.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: 2015-06-12 00:00:00.000000000 Z
11
+ date: 2015-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 0.11.1
47
+ version: 0.11.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 0.11.1
54
+ version: 0.11.2
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: ice_nine
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -254,14 +254,14 @@ dependencies:
254
254
  requirements:
255
255
  - - "~>"
256
256
  - !ruby/object:Gem::Version
257
- version: 0.28.0
257
+ version: 0.33.0
258
258
  type: :development
259
259
  prerelease: false
260
260
  version_requirements: !ruby/object:Gem::Requirement
261
261
  requirements:
262
262
  - - "~>"
263
263
  - !ruby/object:Gem::Version
264
- version: 0.28.0
264
+ version: 0.33.0
265
265
  description: ChatOps for Ruby.
266
266
  email:
267
267
  - jimmy@jimmycuadra.com
@@ -368,6 +368,7 @@ files:
368
368
  - spec/spec_helper.rb
369
369
  - spec/templates/basic.erb
370
370
  - spec/templates/basic.irc.erb
371
+ - spec/templates/helpers.erb
371
372
  - spec/templates/interpolated.erb
372
373
  - templates/locales/en.yml
373
374
  - templates/plugin/Gemfile
@@ -404,7 +405,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
404
405
  version: '0'
405
406
  requirements: []
406
407
  rubyforge_project:
407
- rubygems_version: 2.4.5
408
+ rubygems_version: 2.4.5.1
408
409
  signing_key:
409
410
  specification_version: 4
410
411
  summary: ChatOps framework for Ruby. Lita is a robot companion for your chat room.
@@ -446,5 +447,5 @@ test_files:
446
447
  - spec/spec_helper.rb
447
448
  - spec/templates/basic.erb
448
449
  - spec/templates/basic.irc.erb
450
+ - spec/templates/helpers.erb
449
451
  - spec/templates/interpolated.erb
450
- has_rdoc: