rita 0.1.0 → 5.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +19 -0
  3. data/.rubocop.yml +51 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +16 -0
  6. data/CONTRIBUTING.md +18 -0
  7. data/Gemfile +5 -0
  8. data/{LICENSE.txt → LICENSE} +1 -3
  9. data/README.md +17 -24
  10. data/Rakefile +5 -5
  11. data/bin/lita +7 -0
  12. data/lib/lita/adapter.rb +147 -0
  13. data/lib/lita/adapters/shell.rb +126 -0
  14. data/lib/lita/adapters/test.rb +62 -0
  15. data/lib/lita/authorization.rb +112 -0
  16. data/lib/lita/callback.rb +39 -0
  17. data/lib/lita/cli.rb +218 -0
  18. data/lib/lita/configurable.rb +47 -0
  19. data/lib/lita/configuration_builder.rb +247 -0
  20. data/lib/lita/configuration_validator.rb +95 -0
  21. data/lib/lita/default_configuration.rb +122 -0
  22. data/lib/lita/errors.rb +25 -0
  23. data/lib/lita/handler/chat_router.rb +141 -0
  24. data/lib/lita/handler/common.rb +208 -0
  25. data/lib/lita/handler/event_router.rb +84 -0
  26. data/lib/lita/handler/http_router.rb +31 -0
  27. data/lib/lita/handler.rb +15 -0
  28. data/lib/lita/handlers/authorization.rb +129 -0
  29. data/lib/lita/handlers/help.rb +171 -0
  30. data/lib/lita/handlers/info.rb +66 -0
  31. data/lib/lita/handlers/room.rb +36 -0
  32. data/lib/lita/handlers/users.rb +37 -0
  33. data/lib/lita/http_callback.rb +46 -0
  34. data/lib/lita/http_route.rb +83 -0
  35. data/lib/lita/logger.rb +43 -0
  36. data/lib/lita/message.rb +124 -0
  37. data/lib/lita/middleware_registry.rb +39 -0
  38. data/lib/lita/namespace.rb +29 -0
  39. data/lib/lita/plugin_builder.rb +43 -0
  40. data/lib/lita/rack_app.rb +100 -0
  41. data/lib/lita/registry.rb +164 -0
  42. data/lib/lita/response.rb +65 -0
  43. data/lib/lita/robot.rb +273 -0
  44. data/lib/lita/room.rb +119 -0
  45. data/lib/lita/route_validator.rb +82 -0
  46. data/lib/lita/rspec/handler.rb +127 -0
  47. data/lib/lita/rspec/matchers/chat_route_matcher.rb +53 -0
  48. data/lib/lita/rspec/matchers/event_route_matcher.rb +29 -0
  49. data/lib/lita/rspec/matchers/http_route_matcher.rb +34 -0
  50. data/lib/lita/rspec.rb +48 -0
  51. data/lib/lita/source.rb +81 -0
  52. data/lib/lita/store.rb +23 -0
  53. data/lib/lita/target.rb +3 -0
  54. data/lib/lita/template.rb +71 -0
  55. data/lib/lita/template_resolver.rb +52 -0
  56. data/lib/lita/timer.rb +49 -0
  57. data/lib/lita/user.rb +157 -0
  58. data/lib/lita/util.rb +31 -0
  59. data/lib/lita/version.rb +6 -0
  60. data/lib/lita.rb +166 -0
  61. data/rita.gemspec +50 -0
  62. data/spec/lita/adapter_spec.rb +54 -0
  63. data/spec/lita/adapters/shell_spec.rb +99 -0
  64. data/spec/lita/authorization_spec.rb +122 -0
  65. data/spec/lita/configuration_builder_spec.rb +247 -0
  66. data/spec/lita/configuration_validator_spec.rb +114 -0
  67. data/spec/lita/default_configuration_spec.rb +242 -0
  68. data/spec/lita/handler/chat_router_spec.rb +236 -0
  69. data/spec/lita/handler/common_spec.rb +289 -0
  70. data/spec/lita/handler/event_router_spec.rb +121 -0
  71. data/spec/lita/handler/http_router_spec.rb +155 -0
  72. data/spec/lita/handler_spec.rb +62 -0
  73. data/spec/lita/handlers/authorization_spec.rb +111 -0
  74. data/spec/lita/handlers/help_spec.rb +124 -0
  75. data/spec/lita/handlers/info_spec.rb +67 -0
  76. data/spec/lita/handlers/room_spec.rb +24 -0
  77. data/spec/lita/handlers/users_spec.rb +35 -0
  78. data/spec/lita/logger_spec.rb +28 -0
  79. data/spec/lita/message_spec.rb +178 -0
  80. data/spec/lita/plugin_builder_spec.rb +41 -0
  81. data/spec/lita/response_spec.rb +62 -0
  82. data/spec/lita/robot_spec.rb +285 -0
  83. data/spec/lita/room_spec.rb +136 -0
  84. data/spec/lita/rspec/handler_spec.rb +33 -0
  85. data/spec/lita/rspec_spec.rb +162 -0
  86. data/spec/lita/source_spec.rb +68 -0
  87. data/spec/lita/store_spec.rb +23 -0
  88. data/spec/lita/template_resolver_spec.rb +42 -0
  89. data/spec/lita/template_spec.rb +52 -0
  90. data/spec/lita/timer_spec.rb +32 -0
  91. data/spec/lita/user_spec.rb +167 -0
  92. data/spec/lita/util_spec.rb +18 -0
  93. data/spec/lita_spec.rb +227 -0
  94. data/spec/spec_helper.rb +35 -0
  95. data/spec/templates/basic.erb +1 -0
  96. data/spec/templates/basic.irc.erb +1 -0
  97. data/spec/templates/helpers.erb +1 -0
  98. data/spec/templates/interpolated.erb +1 -0
  99. data/templates/locales/en.yml +137 -0
  100. data/templates/plugin/Gemfile +5 -0
  101. data/templates/plugin/README.tt +29 -0
  102. data/templates/plugin/Rakefile +8 -0
  103. data/templates/plugin/gemspec.tt +27 -0
  104. data/templates/plugin/gitignore +18 -0
  105. data/templates/plugin/lib/lita/plugin_type/plugin.tt +19 -0
  106. data/templates/plugin/lib/plugin.tt +16 -0
  107. data/templates/plugin/locales/en.yml.tt +4 -0
  108. data/templates/plugin/spec/lita/plugin_type/plugin_spec.tt +6 -0
  109. data/templates/plugin/spec/spec_helper.tt +8 -0
  110. data/templates/plugin/templates/gitkeep +0 -0
  111. data/templates/robot/Gemfile +5 -0
  112. data/templates/robot/lita_config.rb +28 -0
  113. metadata +386 -21
  114. data/.standard.yml +0 -3
  115. data/CHANGELOG.md +0 -5
  116. data/CODE_OF_CONDUCT.md +0 -132
  117. data/lib/rita/version.rb +0 -5
  118. data/lib/rita.rb +0 -8
  119. data/sig/rita.rbs +0 -4
data/lib/lita.rb ADDED
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+
5
+ require "i18n"
6
+ require "i18n/backend/fallbacks"
7
+ require "redis-namespace"
8
+
9
+ require_relative "lita/configuration_builder"
10
+ require_relative "lita/configuration_validator"
11
+ require_relative "lita/errors"
12
+ require_relative "lita/logger"
13
+ require_relative "lita/registry"
14
+ require_relative "lita/robot"
15
+
16
+ # The main namespace for Lita. Provides a global registry of adapters and
17
+ # handlers, as well as global configuration, logger, and Redis store.
18
+ module Lita
19
+ class << self
20
+ include Registry::Mixins
21
+
22
+ # A mode that makes minor changes to the Lita runtime to improve testability.
23
+ # @return [Boolean] Whether or not test mode is active.
24
+ # @since 4.0.0
25
+ attr_reader :test_mode
26
+ alias test_mode? test_mode
27
+
28
+ # Sets both I18n.default_locale and I18n.locale to the provided locale, if any.
29
+ # @api private
30
+ # @since 5.0.0
31
+ def configure_i18n(new_locale)
32
+ unless new_locale.nil?
33
+ self.default_locale = new_locale
34
+ self.locale = new_locale
35
+ end
36
+ end
37
+
38
+ # Lita's global +Logger+.
39
+ #
40
+ # The log level is initially set according to the environment variable +LITA_LOG+, defaulting to
41
+ # +info+ if the variable is not set. Once the user configuration is loaded, the log level will
42
+ # be reset to whatever is specified in the configuration file.
43
+ # @return [::Logger] A +Logger+ object.
44
+ def logger
45
+ @logger ||= Logger.get_logger(
46
+ ENV["LITA_LOG"],
47
+ io: test_mode? ? StringIO.new : $stderr,
48
+ )
49
+ end
50
+
51
+ # Adds one or more paths to the I18n load path and reloads I18n.
52
+ # @param paths [String, Array<String>] The path(s) to add.
53
+ # @return [void]
54
+ # @since 3.0.0
55
+ def load_locales(paths)
56
+ I18n.load_path.concat(Array(paths))
57
+ I18n.reload!
58
+ end
59
+
60
+ # Sets +I18n.locale+, normalizing the provided locale name.
61
+ #
62
+ # Note that setting this only affects the current thread. Since handler
63
+ # methods are dispatched in new threads, changing the locale globally will
64
+ # require calling this method at the start of every handler method.
65
+ # Alternatively, use {Lita#default_locale=} which will affect all threads.
66
+ # @param new_locale [Symbol, String] The code of the locale to use.
67
+ # @return [void]
68
+ # @since 3.0.0
69
+ def locale=(new_locale)
70
+ I18n.locale = new_locale.to_s.tr("_", "-")
71
+ end
72
+
73
+ # Sets +I18n.default_locale+, normalizing the provided locale name.
74
+ #
75
+ # This is preferred over {Lita#locale=} as it affects all threads.
76
+ # @param new_locale [Symbol, String] The code of the locale to use.
77
+ # @return [void]
78
+ # @since 4.8.0
79
+ def default_locale=(new_locale)
80
+ I18n.default_locale = new_locale.to_s.tr("_", "-")
81
+ end
82
+
83
+ # The absolute path to Lita's templates directory.
84
+ # @return [String] The path.
85
+ # @since 3.0.0
86
+ def template_root
87
+ File.expand_path("../templates", __dir__)
88
+ end
89
+
90
+ # Loads user configuration.
91
+ # @param config_path [String] The path to the user configuration file.
92
+ # @return [void]
93
+ def load_config(config_path = nil)
94
+ hooks[:before_run].each { |hook| hook.call(config_path: config_path) }
95
+ ConfigurationBuilder.load_user_config(config_path)
96
+ ConfigurationBuilder.freeze_config(config)
97
+ recreate_logger # Pick up value of `config.robot.log_level` and `config.robot.log_formatter`.
98
+ ConfigurationValidator.new(self).call
99
+ hooks[:config_finalized].each { |hook| hook.call(config_path: config_path) }
100
+
101
+ if config.robot.default_locale || config.robot.locale
102
+ logger.warn I18n.t("lita.config.locale_deprecated")
103
+ self.default_locale = config.robot.default_locale if config.robot.default_locale
104
+ self.locale = config.robot.locale if config.robot.locale
105
+ end
106
+ end
107
+
108
+ # Loads user configuration and starts the robot.
109
+ # @param config_path [String] The path to the user configuration file.
110
+ # @return [void]
111
+ def run(config_path = nil)
112
+ load_config(config_path)
113
+ Robot.new.run
114
+ end
115
+
116
+ # Turns test mode on or off.
117
+ # @param mode [Boolean] Whether or not test mode should be enabled.
118
+ # @return [void]
119
+ # @see #test_mode
120
+ def test_mode=(mode)
121
+ @test_mode = mode
122
+ # Reset the logger because its IO stream is determined by test mode.
123
+ recreate_logger
124
+ end
125
+
126
+ # A special mode to ensure that tests written for Lita 3 plugins continue to work. Has no effect
127
+ # in Lita 5+.
128
+ # @return [Boolean] Whether or not version 3 compatibility mode is active.
129
+ # @since 4.0.0
130
+ # @deprecated Will be removed in Lita 6.0.
131
+ def version_3_compatibility_mode(_value = nil)
132
+ warn I18n.t("lita.rspec.lita_3_compatibility_mode")
133
+ false
134
+ end
135
+ alias version_3_compatibility_mode? version_3_compatibility_mode
136
+ alias version_3_compatibility_mode= version_3_compatibility_mode
137
+
138
+ private
139
+
140
+ # Recreate the logger, specifying the configured log level and output stream. Should be called
141
+ # manually after user configuration has been loaded and whenever test mode is changed. This is
142
+ # necessary because {#logger} does not access the config so as not to accidentally build the
143
+ # {DefaultConfiguration} before all plugins have been loaded and registered.
144
+ def recreate_logger
145
+ @logger = Logger.get_logger(
146
+ config.robot.log_level,
147
+ formatter: config.robot.log_formatter,
148
+ io: test_mode? ? StringIO.new : $stderr,
149
+ )
150
+ end
151
+ end
152
+ end
153
+
154
+ I18n::Backend::Simple.include(I18n::Backend::Fallbacks)
155
+ I18n.enforce_available_locales = false
156
+ Lita.load_locales(Dir[File.join(Lita.template_root, "locales", "*.yml")])
157
+ Lita.configure_i18n(ENV["LC_ALL"] || ENV["LC_MESSAGES"] || ENV["LANG"])
158
+
159
+ require_relative "lita/adapters/shell"
160
+ require_relative "lita/adapters/test"
161
+
162
+ require_relative "lita/handlers/authorization"
163
+ require_relative "lita/handlers/help"
164
+ require_relative "lita/handlers/info"
165
+ require_relative "lita/handlers/room"
166
+ require_relative "lita/handlers/users"
data/rita.gemspec ADDED
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "lita/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "rita"
9
+ spec.version = Lita::VERSION
10
+ spec.authors = ["Jimmy Cuadra"]
11
+ spec.email = ["jimmy@jimmycuadra.com"]
12
+ spec.description = "ChatOps for Ruby."
13
+ spec.summary = "ChatOps framework for Ruby. Rita is a robot companion for your chat room."
14
+ spec.homepage = "https://github.com/ritaio/rita"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.required_ruby_version = ">= 3.0.0"
23
+
24
+ spec.metadata = {
25
+ "bug_tracker_uri" => "https://github.com/ritaio/rita/issues",
26
+ "changelog_uri" => "https://github.com/ritaio/rita/releases",
27
+ # "documentation_uri" => "https://docs.lita.io/",
28
+ # "homepage_uri" => "https://www.lita.io/",
29
+ # "mailing_list_uri" => "https://groups.google.com/group/litaio",
30
+ "source_code_uri" => "https://github.com/ritaio/rita",
31
+ }
32
+
33
+ spec.add_runtime_dependency "bundler", "~> 2.2.3"
34
+ spec.add_runtime_dependency "faraday", "~> 1.6.0"
35
+ spec.add_runtime_dependency "http_router", "~> 0.11.2"
36
+ spec.add_runtime_dependency "i18n", "~> 1.8.10"
37
+ spec.add_runtime_dependency "ice_nine", "~> 0.11.2"
38
+ spec.add_runtime_dependency "puma", "~> 5.4.0"
39
+ spec.add_runtime_dependency "rack", "~> 2.2.3"
40
+ spec.add_runtime_dependency "rb-readline", "~> 0.5.5"
41
+ spec.add_runtime_dependency "redis-namespace", "~> 1.8.1"
42
+ spec.add_runtime_dependency "thor", "~> 1.1.0"
43
+
44
+ spec.add_development_dependency "pry-byebug", "~> 3.9.0"
45
+ spec.add_development_dependency "rack-test", "~> 1.1.0"
46
+ spec.add_development_dependency "rake", "~> 13.0.3"
47
+ spec.add_development_dependency "rspec", "~> 3.10.0"
48
+ spec.add_development_dependency "rubocop", "~> 1.17.0"
49
+ spec.add_development_dependency "simplecov", "~> 0.21.2"
50
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Lita::Adapter, lita: true do
6
+ let(:robot) { Lita::Robot.new(registry) }
7
+
8
+ let(:required_methods) { described_class::REQUIRED_METHODS }
9
+
10
+ subject { described_class.new(robot) }
11
+
12
+ it "stores a Robot" do
13
+ expect(subject.robot).to eql(robot)
14
+ end
15
+
16
+ it "logs a warning if a required method has not been implemented" do
17
+ expect(robot.logger).to receive(:warn).exactly(required_methods.size).times
18
+ required_methods.each do |method|
19
+ subject.public_send(method)
20
+ end
21
+ end
22
+
23
+ describe "#config" do
24
+ let(:adapter) do
25
+ Class.new(described_class) do
26
+ namespace "test"
27
+
28
+ config :foo, default: :bar
29
+ end
30
+ end
31
+
32
+ let(:robot) { Lita::Robot.new(registry) }
33
+
34
+ before { registry.register_adapter(:test, adapter) }
35
+
36
+ subject { adapter.new(robot) }
37
+
38
+ it "provides access to the adapter's configuration object" do
39
+ expect(subject.config.foo).to eq(:bar)
40
+ end
41
+ end
42
+
43
+ describe "#log" do
44
+ it "returns the robot's logger" do
45
+ expect(subject.log).to eq(robot.logger)
46
+ end
47
+ end
48
+
49
+ describe "#mention_format" do
50
+ it "formats the provided name for mentioning the user" do
51
+ expect(subject.mention_format("carl")).to eq("carl:")
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Lita::Adapters::Shell, lita: true do
6
+ let(:robot) do
7
+ instance_double(
8
+ "Lita::Robot",
9
+ name: "Lita",
10
+ mention_name: "LitaBot",
11
+ alias: "/",
12
+ config: registry.config
13
+ )
14
+ end
15
+
16
+ subject { described_class.new(robot) }
17
+
18
+ describe "#roster" do
19
+ let(:room) { instance_double("Lita::Room") }
20
+
21
+ it "returns the shell user" do
22
+ expect(subject.roster(room).first.name).to eq("Shell User")
23
+ end
24
+ end
25
+
26
+ describe "#run" do
27
+ let(:user) { Lita::User.create(1, name: "Shell User") }
28
+
29
+ before do
30
+ registry.register_adapter(:shell, described_class)
31
+ allow(subject).to receive(:puts)
32
+ allow(Readline).to receive(:readline).and_return("foo", "exit")
33
+ allow(robot).to receive(:trigger)
34
+ allow(robot).to receive(:receive)
35
+ allow(Lita::User).to receive(:create).and_return(user)
36
+ end
37
+
38
+ it "passes input to the Robot and breaks on an exit message" do
39
+ expect(Readline).to receive(:readline).with("#{robot.name} > ", true).twice
40
+ expect(robot).to receive(:receive).with(an_instance_of(Lita::Message))
41
+ subject.run
42
+ end
43
+
44
+ it "marks messages as commands if config.adapters.shell.private_chat is true" do
45
+ registry.config.adapters.shell.private_chat = true
46
+ expect_any_instance_of(Lita::Message).to receive(:command!)
47
+ subject.run
48
+ end
49
+
50
+ it "sets the room to 'shell' if config.adapters.shell.private_chat is false" do
51
+ registry.config.adapters.shell.private_chat = false
52
+ expect(Lita::Source).to receive(:new).with(user: user, room: "shell")
53
+ subject.run
54
+ end
55
+
56
+ it "sets the room to nil if config.adapters.shell.private_chat is true" do
57
+ registry.config.adapters.shell.private_chat = true
58
+ expect(Lita::Source).to receive(:new).with(user: user, room: nil)
59
+ subject.run
60
+ end
61
+
62
+ it "triggers a connected event" do
63
+ expect(robot).to receive(:trigger).with(:connected)
64
+ subject.run
65
+ end
66
+
67
+ it "exits cleanly when EOF is received" do
68
+ allow(Readline).to receive(:readline).and_return(nil)
69
+ subject.run
70
+ end
71
+
72
+ it "removes empty input from readline history" do
73
+ allow(Readline).to receive(:readline).and_return("", "exit")
74
+ expect(Readline::HISTORY).to receive(:pop)
75
+ subject.run
76
+ end
77
+ end
78
+
79
+ describe "#send_message" do
80
+ it "prints its input" do
81
+ expect(subject).to receive(:puts) do |messages|
82
+ expect(messages.first).to include("bar")
83
+ end
84
+ subject.send_messages(instance_double("Lita::Source"), "bar")
85
+ end
86
+
87
+ it "doesn't output empty messages" do
88
+ expect(subject).to receive(:puts).with([])
89
+ subject.send_messages(instance_double("Lita::Source"), "")
90
+ end
91
+ end
92
+
93
+ describe "#shut_down" do
94
+ it "outputs a blank line" do
95
+ expect(subject).to receive(:puts)
96
+ subject.shut_down
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Lita::Authorization, lita: true do
6
+ let(:requesting_user) { instance_double("Lita::User", id: "1") }
7
+ let(:robot) { Lita::Robot.new(registry) }
8
+ let(:user) { instance_double("Lita::User", id: "2") }
9
+
10
+ subject { described_class.new(robot) }
11
+
12
+ before do
13
+ registry.config.robot.admins = ["1"]
14
+ end
15
+
16
+ describe "#add_user_to_group" do
17
+ it "adds users to an auth group" do
18
+ subject.add_user_to_group(requesting_user, user, "employees")
19
+ expect(subject.user_in_group?(user, "employees")).to be true
20
+ end
21
+
22
+ it "can only be called by admins" do
23
+ registry.config.robot.admins = nil
24
+ result = subject.add_user_to_group(
25
+ requesting_user,
26
+ user,
27
+ "employees"
28
+ )
29
+ expect(result).to eq(:unauthorized)
30
+ expect(subject.user_in_group?(user, "employees")).to be false
31
+ end
32
+
33
+ it "normalizes the group name" do
34
+ subject.add_user_to_group(requesting_user, user, "eMPLoYeeS")
35
+ expect(subject.user_in_group?(user, " EmplOyEEs ")).to be true
36
+ end
37
+ end
38
+
39
+ describe "#remove_user_from_group" do
40
+ it "removes users from an auth group" do
41
+ subject.add_user_to_group(requesting_user, user, "employees")
42
+ subject.remove_user_from_group(requesting_user, user, "employees")
43
+ expect(subject.user_in_group?(user, "employees")).to be false
44
+ end
45
+
46
+ it "can only be called by admins" do
47
+ subject.add_user_to_group(requesting_user, user, "employees")
48
+ registry.config.robot.admins = nil
49
+ result = subject.remove_user_from_group(
50
+ requesting_user,
51
+ user,
52
+ "employees"
53
+ )
54
+ expect(result).to eq(:unauthorized)
55
+ expect(subject.user_in_group?(user, "employees")).to be true
56
+ end
57
+
58
+ it "normalizes the group name" do
59
+ subject.add_user_to_group(requesting_user, user, "eMPLoYeeS")
60
+ subject.remove_user_from_group(requesting_user, user, "EmployeeS")
61
+ expect(subject.user_in_group?(user, " EmplOyEEs ")).to be false
62
+ end
63
+ end
64
+
65
+ describe "#user_in_group?" do
66
+ it "returns false if the user is in the group" do
67
+ expect(subject.user_in_group?(user, "employees")).to be false
68
+ end
69
+
70
+ it "delegates to .user_is_admin? if the group is admins" do
71
+ expect(subject).to receive(:user_is_admin?)
72
+ subject.user_in_group?(user, "admins")
73
+ end
74
+ end
75
+
76
+ describe "#user_is_admin?" do
77
+ it "returns true if the user's ID is in the config" do
78
+ expect(subject.user_is_admin?(requesting_user)).to be true
79
+ end
80
+
81
+ it "returns false if the user's ID is not in the config" do
82
+ registry.config.robot.admins = nil
83
+ expect(subject.user_is_admin?(user)).to be false
84
+ end
85
+ end
86
+
87
+ describe "#groups" do
88
+ before do
89
+ %i[foo bar baz].each do |group|
90
+ subject.add_user_to_group(requesting_user, user, group)
91
+ end
92
+ end
93
+
94
+ it "returns a list of all authorization groups" do
95
+ expect(subject.groups).to match_array(%i[foo bar baz])
96
+ end
97
+ end
98
+
99
+ describe "#groups_with_users" do
100
+ before do
101
+ %i[foo bar baz].each do |group|
102
+ subject.add_user_to_group(requesting_user, user, group)
103
+ subject.add_user_to_group(
104
+ requesting_user,
105
+ requesting_user,
106
+ group
107
+ )
108
+ end
109
+ allow(Lita::User).to receive(:find_by_id).with("1").and_return(requesting_user)
110
+ allow(Lita::User).to receive(:find_by_id).with("2").and_return(user)
111
+ end
112
+
113
+ it "returns a hash of all authorization groups and their members" do
114
+ groups = %i[foo bar baz]
115
+ groups_with_users = subject.groups_with_users
116
+ expect(groups_with_users.keys).to match_array(groups)
117
+ groups.each do |group|
118
+ expect(groups_with_users[group]).to match_array([user, requesting_user])
119
+ end
120
+ end
121
+ end
122
+ end