lita 2.7.2 → 3.0.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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.rubocop.yml +26 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/README.md +6 -470
  6. data/Rakefile +3 -3
  7. data/lib/lita.rb +27 -19
  8. data/lib/lita/adapter.rb +46 -5
  9. data/lib/lita/adapters/shell.rb +18 -13
  10. data/lib/lita/authorization.rb +1 -1
  11. data/lib/lita/cli.rb +37 -23
  12. data/lib/lita/common.rb +35 -0
  13. data/lib/lita/config.rb +33 -13
  14. data/lib/lita/daemon.rb +15 -12
  15. data/lib/lita/handler.rb +49 -9
  16. data/lib/lita/handlers/authorization.rb +47 -47
  17. data/lib/lita/handlers/help.rb +16 -17
  18. data/lib/lita/handlers/info.rb +38 -0
  19. data/lib/lita/handlers/room.rb +32 -0
  20. data/lib/lita/http_route.rb +30 -19
  21. data/lib/lita/message.rb +3 -6
  22. data/lib/lita/rack_app.rb +11 -89
  23. data/lib/lita/response.rb +5 -15
  24. data/lib/lita/robot.rb +26 -10
  25. data/lib/lita/rspec.rb +6 -8
  26. data/lib/lita/rspec/handler.rb +49 -121
  27. data/lib/lita/rspec/matchers/event_subscription_matcher.rb +67 -0
  28. data/lib/lita/rspec/matchers/http_route_matcher.rb +72 -0
  29. data/lib/lita/rspec/matchers/route_matcher.rb +69 -0
  30. data/lib/lita/source.rb +5 -18
  31. data/lib/lita/timer.rb +45 -0
  32. data/lib/lita/user.rb +51 -4
  33. data/lib/lita/util.rb +5 -5
  34. data/lib/lita/version.rb +1 -1
  35. data/lita.gemspec +6 -3
  36. data/spec/lita/adapter_spec.rb +10 -2
  37. data/spec/lita/adapters/shell_spec.rb +3 -3
  38. data/spec/lita/authorization_spec.rb +11 -11
  39. data/spec/lita/config_spec.rb +8 -0
  40. data/spec/lita/daemon_spec.rb +65 -0
  41. data/spec/lita/handler_spec.rb +50 -11
  42. data/spec/lita/handlers/authorization_spec.rb +1 -1
  43. data/spec/lita/handlers/info_spec.rb +31 -0
  44. data/spec/lita/handlers/room_spec.rb +20 -0
  45. data/spec/lita/logger_spec.rb +1 -1
  46. data/spec/lita/message_spec.rb +4 -4
  47. data/spec/lita/rack_app_spec.rb +92 -0
  48. data/spec/lita/response_spec.rb +17 -8
  49. data/spec/lita/robot_spec.rb +23 -14
  50. data/spec/lita/rspec_spec.rb +1 -1
  51. data/spec/lita/source_spec.rb +0 -16
  52. data/spec/lita/timer_spec.rb +30 -0
  53. data/spec/lita/user_spec.rb +66 -6
  54. data/spec/lita_spec.rb +37 -0
  55. data/spec/spec_helper.rb +11 -0
  56. data/templates/locales/en.yml +90 -0
  57. data/templates/plugin/Rakefile +1 -1
  58. data/templates/plugin/lib/lita/plugin_type/plugin.tt +4 -0
  59. data/templates/plugin/locales/en.yml.tt +4 -0
  60. metadata +77 -18
  61. data/lib/lita/handlers/web.rb +0 -25
  62. data/spec/lita/handlers/web_spec.rb +0 -19
@@ -26,10 +26,7 @@ module Lita
26
26
  @source = source
27
27
 
28
28
  name_pattern = Regexp.escape(@robot.mention_name)
29
-
30
- if @robot.alias
31
- name_pattern = "#{name_pattern}|#{Regexp.escape(@robot.alias)}"
32
- end
29
+ name_pattern = "#{name_pattern}|#{Regexp.escape(@robot.alias)}" if @robot.alias
33
30
 
34
31
  @command = !!@body.sub!(/^\s*@?(?:#{name_pattern})[:,]?\s*/i, "")
35
32
  end
@@ -39,9 +36,9 @@ module Lita
39
36
  # @return [Array<String>] The array of arguments.
40
37
  def args
41
38
  begin
42
- command, *args = body.shellsplit
39
+ _command, *args = body.shellsplit
43
40
  rescue ArgumentError
44
- command, *args =
41
+ _command, *args =
45
42
  body.split(/\s+/).map(&:shellescape).join(" ").shellsplit
46
43
  end
47
44
 
@@ -1,114 +1,36 @@
1
1
  module Lita
2
2
  # A +Rack+ application to serve routes registered by handlers.
3
3
  class RackApp
4
- # The character that separates the pieces of a URL's path component.
5
- PATH_SEPARATOR = "/"
6
-
7
- # A +Struct+ representing a route's destination handler and method name.
8
- RouteMapping = Struct.new(:handler, :method_name)
9
-
10
- # All registered paths. Used to respond to HEAD requests.
11
- # @return [Array<String>] The array of paths.
12
- attr_reader :all_paths
13
-
14
4
  # The currently running robot.
15
5
  # @return [Lita::Robot] The robot.
16
6
  attr_reader :robot
17
7
 
18
- # A hash mapping HTTP request methods and paths to handlers and methods.
19
- # @return [Hash] The mapping.
20
- attr_reader :routes
8
+ # An +HttpRouter+ used for dispatch.
9
+ # @return [HttpRouter] The router.
10
+ attr_reader :router
21
11
 
22
12
  # @param robot [Lita::Robot] The currently running robot.
23
13
  def initialize(robot)
24
14
  @robot = robot
25
- @routes = Hash.new { |h, k| h[k] = {} }
15
+ @router = HttpRouter.new
26
16
  compile
27
17
  end
28
18
 
19
+ # Entry point for Lita's HTTP routes. Invokes the Rack application.
20
+ # @param env [Hash] A Rack environment.
21
+ # @return [void]
29
22
  def call(env)
30
- request = Rack::Request.new(env)
31
- mapping = get_mapping(request)
32
-
33
- if mapping
34
- serve(mapping, request)
35
- elsif request.head? && all_paths.include?(request.path)
36
- Lita.logger.info "HTTP HEAD #{request.path} was a 204."
37
- [204, {}, []]
38
- else
39
- Lita.logger.info <<-LOG.chomp
40
- HTTP #{request.request_method} #{request.path} was a 404.
41
- LOG
42
- [404, {}, ["Route not found."]]
43
- end
44
- end
45
-
46
- # Creates a +Rack+ application from the compiled routes.
47
- # @return [Rack::Builder] The +Rack+ application.
48
- def to_app
49
- app = Rack::Builder.new
50
- app.run(self)
51
- app
23
+ env["lita.robot"] = robot
24
+ router.call(env)
52
25
  end
53
26
 
54
27
  private
55
28
 
56
- # Collect all registered paths. Used for responding to HEAD requests.
57
- def collect_paths
58
- @all_paths = routes.values.map { |hash| hash.keys.first }.uniq
59
- end
60
-
61
- # Registers routes in the route mapping for each handler's defined routes.
29
+ # Registers routes in the router for each handler's defined routes.
62
30
  def compile
63
31
  Lita.handlers.each do |handler|
64
- handler.http_routes.each { |route| register_route(handler, route) }
65
- end
66
- collect_paths
67
- end
68
-
69
- def get_mapping(request)
70
- routes[request.request_method][request.path]
71
- end
72
-
73
- # Registers a route.
74
- def register_route(handler, route)
75
- cleaned_path = clean_path(route.path)
76
-
77
- if @routes[route.http_method][cleaned_path]
78
- Lita.logger.fatal <<-ERR.chomp
79
- #{handler.name} attempted to register an HTTP route that was already \
80
- registered: #{route.http_method} "#{cleaned_path}"
81
- ERR
82
- abort
32
+ handler.http_routes.each { |route| router.add_route(route) }
83
33
  end
84
-
85
- Lita.logger.debug <<-LOG.chomp
86
- Registering HTTP route: #{route.http_method} #{cleaned_path} to \
87
- #{handler}##{route.method_name}.
88
- LOG
89
- @routes[route.http_method][cleaned_path] = RouteMapping.new(
90
- handler,
91
- route.method_name
92
- )
93
- end
94
-
95
- def serve(mapping, request)
96
- Lita.logger.info <<-LOG.chomp
97
- Routing HTTP #{request.request_method} #{request.path} to \
98
- #{mapping.handler}##{mapping.method_name}.
99
- LOG
100
- response = Rack::Response.new
101
- instance = mapping.handler.new(robot)
102
- instance.public_send(mapping.method_name, request, response)
103
- response.finish
104
- end
105
-
106
- # Ensures that paths begin with one slash and do not end with one.
107
- def clean_path(path)
108
- path.strip!
109
- path.chop! while path.end_with?(PATH_SEPARATOR)
110
- path = path[1..-1] while path.start_with?(PATH_SEPARATOR)
111
- "/#{path}"
112
34
  end
113
35
  end
114
36
  end
@@ -23,20 +23,10 @@ module Lita
23
23
  def_delegators :message, :args, :reply, :reply_privately, :user, :command?
24
24
 
25
25
  # @param message [Lita::Message] The incoming message.
26
- # @param matches [Regexp] The pattern the incoming message matched.
27
- def initialize(*args)
28
- options = args.last.is_a?(Hash) ? args.pop : {}
29
-
30
- self.message = args[0]
31
- self.pattern = args[1]
32
-
33
- if options[:matches]
34
- Lita.logger.warn <<-WARNING.chomp
35
- Passing a "matches" option to Response's constructor is deprecated. \
36
- Use Response.new(message, pattern) instead.
37
- WARNING
38
- @matches = options[:matches]
39
- end
26
+ # @param pattern [Regexp] The pattern the incoming message matched.
27
+ def initialize(message, pattern)
28
+ self.message = message
29
+ self.pattern = pattern
40
30
  end
41
31
 
42
32
  # An array of matches from scanning the message against the route pattern.
@@ -48,7 +38,7 @@ Use Response.new(message, pattern) instead.
48
38
  # A +MatchData+ object from running the pattern against the message body.
49
39
  # @return [MatchData] The +MatchData+.
50
40
  def match_data
51
- @match_data ||= pattern.match(message.body) if pattern
41
+ @match_data ||= pattern.match(message.body)
52
42
  end
53
43
  end
54
44
  end
@@ -26,7 +26,7 @@ module Lita
26
26
  @name = Lita.config.robot.name
27
27
  @mention_name = Lita.config.robot.mention_name || @name
28
28
  @alias = Lita.config.robot.alias
29
- @app = RackApp.new(self).to_app
29
+ @app = RackApp.new(self)
30
30
  load_adapter
31
31
  trigger(:loaded)
32
32
  end
@@ -49,6 +49,22 @@ module Lita
49
49
  shut_down
50
50
  end
51
51
 
52
+ # Makes the robot join a room with the specified ID.
53
+ # @param room_id [String] The ID of the room.
54
+ # @return [void]
55
+ # @since 3.0.0
56
+ def join(room_id)
57
+ @adapter.join(room_id)
58
+ end
59
+
60
+ # Makes the robot part from the room with the specified ID.
61
+ # @param room_id [String] The ID of the room.
62
+ # @return [void]
63
+ # @since 3.0.0
64
+ def part(room_id)
65
+ @adapter.part(room_id)
66
+ end
67
+
52
68
  # Sends one or more messages to a user or room.
53
69
  # @param target [Lita::Source] The user or room to send to. If the Source
54
70
  # has a room, it will choose the room. Otherwise, it will send to the
@@ -74,7 +90,7 @@ module Lita
74
90
  # @return [void]
75
91
  def shut_down
76
92
  trigger(:shut_down_started)
77
- @server.stop if @server
93
+ @server.stop(true) if @server
78
94
  @server_thread.join if @server_thread
79
95
  @adapter.shut_down
80
96
  trigger(:shut_down_complete)
@@ -100,7 +116,7 @@ module Lita
100
116
  adapter_class = Lita.adapters[adapter_name.to_sym]
101
117
 
102
118
  unless adapter_class
103
- Lita.logger.fatal("Unknown adapter: :#{adapter_name}.")
119
+ Lita.logger.fatal I18n.t("lita.robot.unknown_adapter", adapter: adapter_name)
104
120
  abort
105
121
  end
106
122
 
@@ -109,14 +125,14 @@ module Lita
109
125
 
110
126
  # Starts the web server.
111
127
  def run_app
128
+ http_config = Lita.config.http
129
+
112
130
  @server_thread = Thread.new do
113
- @server = Thin::Server.new(
114
- app,
115
- Lita.config.http.port.to_i,
116
- signals: false
117
- )
118
- @server.silent = true unless Lita.config.http.debug
119
- @server.start
131
+ @server = Puma::Server.new(app)
132
+ @server.add_tcp_listener(http_config.host, http_config.port.to_i)
133
+ @server.min_threads = http_config.min_threads
134
+ @server.max_threads = http_config.max_threads
135
+ @server.run
120
136
  end
121
137
 
122
138
  @server_thread.abort_on_exception = true
@@ -3,15 +3,13 @@ begin
3
3
  require "rspec/expectations"
4
4
  require "rspec/mocks"
5
5
  rescue LoadError
6
- abort "Lita::RSpec requires both RSpec::Mocks and RSpec::Expectations."
6
+ abort I18n.t("lita.rspec.full_suite_required")
7
7
  end
8
8
 
9
- major, minor, patch, *pre = RSpec::Mocks::Version::STRING.split(/\./)
10
- if major == "2" && minor.to_i < 14
11
- abort "RSpec::Mocks 2.14 or greater is required to use Lita::RSpec."
12
- end
9
+ major, minor, _patch, *_pre = RSpec::Mocks::Version::STRING.split(/\./)
10
+ abort I18n.t("lita.rspec.mocks_expect_syntax_required") if major == "2" && minor.to_i < 14
13
11
 
14
- require "lita/rspec/handler"
12
+ require_relative "rspec/handler"
15
13
 
16
14
  module Lita
17
15
  # Extras for +RSpec+ that facilitate the testing of Lita code.
@@ -32,14 +30,14 @@ module Lita
32
30
  end
33
31
  end
34
32
 
35
- set_up_redis(base)
33
+ prepare_redis(base)
36
34
  end
37
35
 
38
36
  private
39
37
 
40
38
  # Set up Redis to use the test namespace and clear out before each
41
39
  # example.
42
- def set_up_redis(base)
40
+ def prepare_redis(base)
43
41
  base.class_eval do
44
42
  before do
45
43
  stub_const("Lita::REDIS_NAMESPACE", "lita.test")
@@ -1,3 +1,7 @@
1
+ require_relative "matchers/route_matcher"
2
+ require_relative "matchers/http_route_matcher"
3
+ require_relative "matchers/event_subscription_matcher"
4
+
1
5
  module Lita
2
6
  module RSpec
3
7
  # Extras for +RSpec+ to facilitate testing Lita handlers.
@@ -9,29 +13,23 @@ module Lita
9
13
  include Lita::RSpec
10
14
  end
11
15
 
12
- set_up_let_blocks(base)
13
- set_up_subject(base)
14
- set_up_before_block(base)
16
+ prepare_handlers(base)
17
+ prepare_let_blocks(base)
18
+ prepare_subject(base)
19
+ prepare_robot(base)
15
20
  end
16
21
 
17
22
  private
18
23
 
19
- # Stub Lita.handlers and Lita::Robot#send_messages.
20
- def set_up_before_block(base)
24
+ # Stub Lita.handlers.
25
+ def prepare_handlers(base)
21
26
  base.class_eval do
22
- before do
23
- allow(Lita).to receive(:handlers).and_return([described_class])
24
- [:send_messages, :send_message].each do |message|
25
- allow(robot).to receive(message) do |target, *strings|
26
- replies.concat(strings)
27
- end
28
- end
29
- end
27
+ before { allow(Lita).to receive(:handlers).and_return([described_class]) }
30
28
  end
31
29
  end
32
30
 
33
31
  # Create common test objects.
34
- def set_up_let_blocks(base)
32
+ def prepare_let_blocks(base)
35
33
  base.class_eval do
36
34
  let(:robot) { Robot.new }
37
35
  let(:source) { Source.new(user: user) }
@@ -40,10 +38,24 @@ module Lita
40
38
  end
41
39
  end
42
40
 
41
+ # Stub Lita::Robot#send_messages.
42
+ def prepare_robot(base)
43
+ base.class_eval do
44
+ before do
45
+ [:send_messages, :send_message].each do |message|
46
+ allow(robot).to receive(message) do |target, *strings|
47
+ replies.concat(strings)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
43
54
  # Set up a working test subject.
44
- def set_up_subject(base)
55
+ def prepare_subject(base)
45
56
  base.class_eval do
46
57
  subject { described_class.new(robot) }
58
+ before { allow(described_class).to receive(:new).and_return(subject) }
47
59
  end
48
60
  end
49
61
  end
@@ -73,42 +85,38 @@ module Lita
73
85
  # Starts a chat routing test chain, asserting that a message should
74
86
  # trigger a route.
75
87
  # @param message [String] The message that should trigger the route.
76
- # @return [RouteMatcher] A {RouteMatcher} that should have +to+ called on
77
- # it to complete the test.
88
+ # @return [Matchers::RouteMatcher] A {Matchers::RouteMatcher} that should have +to+
89
+ # called on it to complete the test.
78
90
  def routes(message)
79
- RouteMatcher.new(self, message)
91
+ Matchers::RouteMatcher.new(self, message)
80
92
  end
81
93
 
82
94
  # Starts a chat routing test chain, asserting that a message should not
83
95
  # trigger a route.
84
96
  # @param message [String] The message that should not trigger the route.
85
- # @return [RouteMatcher] A {RouteMatcher} that should have +to+ called on
86
- # it to complete the test.
97
+ # @return [Matchers::RouteMatcher] A {Matchers::RouteMatcher} that should have +to+
98
+ # called on it to complete the test.
87
99
  def does_not_route(message)
88
- RouteMatcher.new(self, message, invert: true)
100
+ Matchers::RouteMatcher.new(self, message, expectation: false)
89
101
  end
90
102
  alias_method :doesnt_route, :does_not_route
91
103
 
92
104
  # Starts a chat routing test chain, asserting that a "command" message
93
105
  # should trigger a route.
94
106
  # @param message [String] The message that should trigger the route.
95
- # @return [RouteMatcher] A {RouteMatcher} that should have +to+ called on
96
- # it to complete the test.
107
+ # @return [Matchers::RouteMatcher] A {Matchers::RouteMatcher} that should have +to+
108
+ # called on it to complete the test.
97
109
  def routes_command(message)
98
- RouteMatcher.new(self, "#{robot.mention_name}: #{message}")
110
+ Matchers::RouteMatcher.new(self, "#{robot.mention_name}: #{message}")
99
111
  end
100
112
 
101
113
  # Starts a chat routing test chain, asserting that a "command" message
102
114
  # should not trigger a route.
103
115
  # @param message [String] The message that should not trigger the route.
104
- # @return [RouteMatcher] A {RouteMatcher} that should have +to+ called on
105
- # it to complete the test.
116
+ # @return [Matchers::RouteMatcher] A {Matchers::RouteMatcher} that should have +to+
117
+ # called on it to complete the test.
106
118
  def does_not_route_command(message)
107
- RouteMatcher.new(
108
- self,
109
- "#{robot.mention_name}: #{message}",
110
- invert: true
111
- )
119
+ Matchers::RouteMatcher.new(self, "#{robot.mention_name}: #{message}", expectation: false)
112
120
  end
113
121
  alias_method :doesnt_route_command, :does_not_route_command
114
122
 
@@ -118,10 +126,10 @@ module Lita
118
126
  # the route.
119
127
  # @param path [String] The path URL component that should trigger the
120
128
  # route.
121
- # @return [HTTPRouteMatcher] An {HTTPRouteMatcher} that should have +to+
122
- # called on it to complete the test.
129
+ # @return [Matchers::HTTPRouteMatcher] A {Matchers::HTTPRouteMatcher} that should
130
+ # have +to+ called on it to complete the test.
123
131
  def routes_http(http_method, path)
124
- HTTPRouteMatcher.new(self, http_method, path)
132
+ Matchers::HTTPRouteMatcher.new(self, http_method, path)
125
133
  end
126
134
 
127
135
  # Starts an HTTP routing test chain, asserting that a request to the given
@@ -130,10 +138,10 @@ module Lita
130
138
  # trigger the route.
131
139
  # @param path [String] The path URL component that should not trigger the
132
140
  # route.
133
- # @return [HTTPRouteMatcher] An {HTTPRouteMatcher} that should have +to+
134
- # called on it to complete the test.
141
+ # @return [Matchers::HTTPRouteMatcher] A {Matchers::HTTPRouteMatcher} that should
142
+ # have +to+ called on it to complete the test.
135
143
  def does_not_route_http(http_method, path)
136
- HTTPRouteMatcher.new(self, http_method, path, invert: true)
144
+ Matchers::HTTPRouteMatcher.new(self, http_method, path, expectation: false)
137
145
  end
138
146
  alias_method :doesnt_route_http, :does_not_route_http
139
147
 
@@ -141,102 +149,22 @@ module Lita
141
149
  # trigger the target method.
142
150
  # @param event_name [String, Symbol] The name of the event that should
143
151
  # be triggered.
144
- # @return [EventSubscriptionMatcher] An {EventSubscriptionMatcher} that
152
+ # @return [Matchers::EventSubscriptionMatcher] A {Matchers::EventSubscriptionMatcher} that
145
153
  # should have +to+ called on it to complete the test.
146
154
  def routes_event(event_name)
147
- EventSubscriptionMatcher.new(self, event_name)
155
+ Matchers::EventSubscriptionMatcher.new(self, event_name)
148
156
  end
149
157
 
150
158
  # Starts an event subscription test chain, asserting that an event should
151
159
  # not trigger the target method.
152
160
  # @param event_name [String, Symbol] The name of the event that should
153
161
  # not be triggered.
154
- # @return [EventSubscriptionMatcher] An {EventSubscriptionMatcher} that
162
+ # @return [Matchers::EventSubscriptionMatcher] A {Matchers::EventSubscriptionMatcher} that
155
163
  # should have +to+ called on it to complete the test.
156
164
  def does_not_route_event(event_name)
157
- EventSubscriptionMatcher.new(self, event_name, invert: true)
165
+ Matchers::EventSubscriptionMatcher.new(self, event_name, expectation: false)
158
166
  end
159
167
  alias_method :doesnt_route_event, :does_not_route_event
160
168
  end
161
-
162
- # Used to complete a chat routing test chain.
163
- class RouteMatcher
164
- def initialize(context, message_body, invert: false)
165
- @context = context
166
- @message_body = message_body
167
- @method = invert ? :not_to : :to
168
- end
169
-
170
- # Sets an expectation that a route will or will not be triggered, then
171
- # sends the message originally provided.
172
- # @param route [Symbol] The name of the method that should or should not
173
- # be triggered.
174
- # @return [void]
175
- def to(route)
176
- m = @method
177
- b = @message_body
178
-
179
- @context.instance_eval do
180
- allow(Authorization).to receive(:user_in_group?).and_return(true)
181
- expect_any_instance_of(described_class).public_send(m, receive(route))
182
- send_message(b)
183
- end
184
- end
185
- end
186
-
187
- # Used to complete an HTTP routing test chain.
188
- class HTTPRouteMatcher
189
- def initialize(context, http_method, path, invert: false)
190
- @context = context
191
- @http_method = http_method
192
- @path = path
193
- @method = invert ? :not_to : :to
194
- end
195
-
196
- # Sets an expectation that an HTTP route will or will not be triggered,
197
- # then makes an HTTP request against the app with the HTTP request
198
- # method and path originally provided.
199
- # @param route [Symbol] The name of the method that should or should not
200
- # be triggered.
201
- # @return [void]
202
- def to(route)
203
- m = @method
204
- h = @http_method
205
- p = @path
206
-
207
- @context.instance_eval do
208
- expect_any_instance_of(described_class).public_send(m, receive(route))
209
- env = Rack::MockRequest.env_for(p, method: h)
210
- robot.app.call(env)
211
- end
212
- end
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
241
169
  end
242
170
  end