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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.rubocop.yml +26 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +6 -470
- data/Rakefile +3 -3
- data/lib/lita.rb +27 -19
- data/lib/lita/adapter.rb +46 -5
- data/lib/lita/adapters/shell.rb +18 -13
- data/lib/lita/authorization.rb +1 -1
- data/lib/lita/cli.rb +37 -23
- data/lib/lita/common.rb +35 -0
- data/lib/lita/config.rb +33 -13
- data/lib/lita/daemon.rb +15 -12
- data/lib/lita/handler.rb +49 -9
- data/lib/lita/handlers/authorization.rb +47 -47
- data/lib/lita/handlers/help.rb +16 -17
- data/lib/lita/handlers/info.rb +38 -0
- data/lib/lita/handlers/room.rb +32 -0
- data/lib/lita/http_route.rb +30 -19
- data/lib/lita/message.rb +3 -6
- data/lib/lita/rack_app.rb +11 -89
- data/lib/lita/response.rb +5 -15
- data/lib/lita/robot.rb +26 -10
- data/lib/lita/rspec.rb +6 -8
- data/lib/lita/rspec/handler.rb +49 -121
- data/lib/lita/rspec/matchers/event_subscription_matcher.rb +67 -0
- data/lib/lita/rspec/matchers/http_route_matcher.rb +72 -0
- data/lib/lita/rspec/matchers/route_matcher.rb +69 -0
- data/lib/lita/source.rb +5 -18
- data/lib/lita/timer.rb +45 -0
- data/lib/lita/user.rb +51 -4
- data/lib/lita/util.rb +5 -5
- data/lib/lita/version.rb +1 -1
- data/lita.gemspec +6 -3
- data/spec/lita/adapter_spec.rb +10 -2
- data/spec/lita/adapters/shell_spec.rb +3 -3
- data/spec/lita/authorization_spec.rb +11 -11
- data/spec/lita/config_spec.rb +8 -0
- data/spec/lita/daemon_spec.rb +65 -0
- data/spec/lita/handler_spec.rb +50 -11
- data/spec/lita/handlers/authorization_spec.rb +1 -1
- data/spec/lita/handlers/info_spec.rb +31 -0
- data/spec/lita/handlers/room_spec.rb +20 -0
- data/spec/lita/logger_spec.rb +1 -1
- data/spec/lita/message_spec.rb +4 -4
- data/spec/lita/rack_app_spec.rb +92 -0
- data/spec/lita/response_spec.rb +17 -8
- data/spec/lita/robot_spec.rb +23 -14
- data/spec/lita/rspec_spec.rb +1 -1
- data/spec/lita/source_spec.rb +0 -16
- data/spec/lita/timer_spec.rb +30 -0
- data/spec/lita/user_spec.rb +66 -6
- data/spec/lita_spec.rb +37 -0
- data/spec/spec_helper.rb +11 -0
- data/templates/locales/en.yml +90 -0
- data/templates/plugin/Rakefile +1 -1
- data/templates/plugin/lib/lita/plugin_type/plugin.tt +4 -0
- data/templates/plugin/locales/en.yml.tt +4 -0
- metadata +77 -18
- data/lib/lita/handlers/web.rb +0 -25
- data/spec/lita/handlers/web_spec.rb +0 -19
data/spec/lita/response_spec.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Lita::Response do
|
4
|
-
subject { described_class.new(message,
|
4
|
+
subject { described_class.new(message, /dummy regexp/) }
|
5
5
|
|
6
|
-
let(:message) {
|
7
|
-
let(:pattern) { double("Regexp").as_null_object }
|
6
|
+
let(:message) { instance_double("Lita::Message").as_null_object }
|
8
7
|
|
9
8
|
[:args, :reply, :user, :command?].each do |method|
|
10
9
|
it "delegates :#{method} to #message" do
|
@@ -13,10 +12,20 @@ describe Lita::Response do
|
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
|
-
matches
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
describe "#matches" do
|
16
|
+
it "matches the pattern against the message" do
|
17
|
+
expect(message).to receive(:match).with(subject.pattern)
|
18
|
+
subject.matches
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#match_data" do
|
23
|
+
let(:body) { instance_double("String") }
|
24
|
+
|
25
|
+
it "matches the message body against the pattern" do
|
26
|
+
allow(message).to receive(:body).and_return(body)
|
27
|
+
expect(subject.pattern).to receive(:match).with(message.body)
|
28
|
+
subject.match_data
|
29
|
+
end
|
21
30
|
end
|
22
31
|
end
|
data/spec/lita/robot_spec.rb
CHANGED
@@ -15,8 +15,8 @@ describe Lita::Robot do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
context "with registered handlers" do
|
18
|
-
let(:handler1) {
|
19
|
-
let(:handler2) {
|
18
|
+
let(:handler1) { class_double("Lita::Handler", http_routes: [], trigger: nil) }
|
19
|
+
let(:handler2) { class_double("Lita::Handler", http_routes: [], trigger: nil) }
|
20
20
|
|
21
21
|
before do
|
22
22
|
allow(Lita).to receive(:handlers).and_return([handler1, handler2])
|
@@ -40,11 +40,12 @@ describe Lita::Robot do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
describe "#run" do
|
43
|
-
let(:thread) {
|
43
|
+
let(:thread) { instance_double("Thread", :abort_on_exception= => true, join: nil) }
|
44
44
|
|
45
45
|
before do
|
46
46
|
allow_any_instance_of(Lita::Adapters::Shell).to receive(:run)
|
47
|
-
allow_any_instance_of(
|
47
|
+
allow_any_instance_of(Puma::Server).to receive(:run)
|
48
|
+
allow_any_instance_of(Puma::Server).to receive(:add_tcp_listener)
|
48
49
|
|
49
50
|
allow(Thread).to receive(:new) do |&block|
|
50
51
|
block.call
|
@@ -58,13 +59,7 @@ describe Lita::Robot do
|
|
58
59
|
end
|
59
60
|
|
60
61
|
it "starts the web server" do
|
61
|
-
expect_any_instance_of(
|
62
|
-
subject.run
|
63
|
-
end
|
64
|
-
|
65
|
-
it "doesn't silence thin if config.http.debug is true" do
|
66
|
-
Lita.config.http.debug = true
|
67
|
-
expect_any_instance_of(Thin::Server).not_to receive(:silent=)
|
62
|
+
expect_any_instance_of(Puma::Server).to receive(:run)
|
68
63
|
subject.run
|
69
64
|
end
|
70
65
|
|
@@ -77,21 +72,35 @@ describe Lita::Robot do
|
|
77
72
|
end
|
78
73
|
end
|
79
74
|
|
75
|
+
describe "#join" do
|
76
|
+
it "delegates to the adapter" do
|
77
|
+
expect_any_instance_of(Lita::Adapters::Shell).to receive(:join).with("#lita.io")
|
78
|
+
subject.join("#lita.io")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#part" do
|
83
|
+
it "delegates to the adapter" do
|
84
|
+
expect_any_instance_of(Lita::Adapters::Shell).to receive(:part).with("#lita.io")
|
85
|
+
subject.part("#lita.io")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
80
89
|
describe "#send_message" do
|
81
|
-
let(:source) {
|
90
|
+
let(:source) { instance_double("Lita::Source") }
|
82
91
|
|
83
92
|
it "delegates to the adapter" do
|
84
93
|
expect_any_instance_of(
|
85
94
|
Lita::Adapters::Shell
|
86
95
|
).to receive(:send_messages).with(
|
87
|
-
source,
|
96
|
+
source, %w(foo bar)
|
88
97
|
)
|
89
98
|
subject.send_messages(source, "foo", "bar")
|
90
99
|
end
|
91
100
|
end
|
92
101
|
|
93
102
|
describe "#set_topic" do
|
94
|
-
let(:source) {
|
103
|
+
let(:source) { instance_double("Lita::Source") }
|
95
104
|
|
96
105
|
it "delegates to the adapter" do
|
97
106
|
expect_any_instance_of(Lita::Adapters::Shell).to receive(:set_topic).with(
|
data/spec/lita/rspec_spec.rb
CHANGED
data/spec/lita/source_spec.rb
CHANGED
@@ -25,20 +25,4 @@ describe Lita::Source do
|
|
25
25
|
it "requires either a user or a room" do
|
26
26
|
expect { described_class.new }.to raise_error(ArgumentError)
|
27
27
|
end
|
28
|
-
|
29
|
-
describe "the deprecated Source.new(user, room) API" do
|
30
|
-
it "can have a user and is marked as private if there is no room" do
|
31
|
-
expect(Lita.logger).to receive(:warn)
|
32
|
-
subject = described_class.new("Carl")
|
33
|
-
expect(subject.user).to eq("Carl")
|
34
|
-
expect(subject).to be_a_private_message
|
35
|
-
end
|
36
|
-
|
37
|
-
it "can have a room and is not marked as private if it does" do
|
38
|
-
expect(Lita.logger).to receive(:warn)
|
39
|
-
subject = described_class.new("Carl", "#litabot")
|
40
|
-
expect(subject.room).to eq("#litabot")
|
41
|
-
expect(subject).not_to be_a_private_message
|
42
|
-
end
|
43
|
-
end
|
44
28
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Lita::Timer do
|
4
|
+
let(:queue) { Queue.new }
|
5
|
+
|
6
|
+
before { allow(subject).to receive(:sleep) }
|
7
|
+
|
8
|
+
after { subject.stop }
|
9
|
+
|
10
|
+
it "runs single timers" do
|
11
|
+
subject = described_class.new { queue.push(true) }
|
12
|
+
expect(subject).to receive(:sleep).with(0).once
|
13
|
+
subject.start
|
14
|
+
expect(queue.pop(true)).to be(true)
|
15
|
+
expect { queue.pop(true) }.to raise_error(ThreadError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "runs recurring timers" do
|
19
|
+
halt = false
|
20
|
+
subject = described_class.new(interval: 1, recurring: true) do |timer|
|
21
|
+
queue.push(true)
|
22
|
+
timer.stop if halt
|
23
|
+
halt = true
|
24
|
+
end
|
25
|
+
expect(subject).to receive(:sleep).with(1).twice
|
26
|
+
subject.start
|
27
|
+
2.times { expect(queue.pop(true)).to be(true) }
|
28
|
+
expect { queue.pop(true) }.to raise_error(ThreadError)
|
29
|
+
end
|
30
|
+
end
|
data/spec/lita/user_spec.rb
CHANGED
@@ -9,12 +9,9 @@ describe Lita::User, lita: true do
|
|
9
9
|
persisted_user = described_class.find(1)
|
10
10
|
expect(user).to eq(persisted_user)
|
11
11
|
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe ".find" do
|
15
|
-
before { described_class.create(1, name: "Carl") }
|
16
12
|
|
17
13
|
it "returns existing users" do
|
14
|
+
described_class.create(1, name: "Carl")
|
18
15
|
expect_any_instance_of(described_class).not_to receive(:save)
|
19
16
|
user = described_class.find(1, name: "Carl")
|
20
17
|
expect(user.id).to eq("1")
|
@@ -22,6 +19,26 @@ describe Lita::User, lita: true do
|
|
22
19
|
end
|
23
20
|
end
|
24
21
|
|
22
|
+
describe ".find_by_id" do
|
23
|
+
it "finds users with no metadata stored" do
|
24
|
+
described_class.create(1)
|
25
|
+
user = described_class.find_by_id(1)
|
26
|
+
expect(user.id).to eq("1")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".find_by_mention_name" do
|
31
|
+
it "returns nil if no user matches the provided mention name" do
|
32
|
+
expect(described_class.find_by_mention_name("carlthepug")).to be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns a user that matches the provided mention name" do
|
36
|
+
described_class.create(1, mention_name: "carlthepug")
|
37
|
+
user = described_class.find_by_mention_name("carlthepug")
|
38
|
+
expect(user.id).to eq("1")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
25
42
|
describe ".find_by_name" do
|
26
43
|
it "returns nil if no user matches the provided name" do
|
27
44
|
expect(described_class.find_by_name("Carl")).to be_nil
|
@@ -34,18 +51,61 @@ describe Lita::User, lita: true do
|
|
34
51
|
end
|
35
52
|
end
|
36
53
|
|
54
|
+
describe ".find_by_partial_name" do
|
55
|
+
before { described_class.create(1, name: "José Vicente Cuadra") }
|
56
|
+
|
57
|
+
it "finds users by partial name match" do
|
58
|
+
user = described_class.find_by_partial_name("José")
|
59
|
+
expect(user.id).to eq("1")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns nil if no users' names start with the provided string" do
|
63
|
+
expect(described_class.find_by_partial_name("Foo")).to be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns nil if more than one match was found" do
|
67
|
+
described_class.create(2, name: "José Contreras")
|
68
|
+
expect(described_class.find_by_partial_name("José")).to be_nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe ".fuzzy_find" do
|
73
|
+
let!(:user) { described_class.create(1, name: "Carl the Pug", mention_name: "carlthepug") }
|
74
|
+
|
75
|
+
it "finds by ID" do
|
76
|
+
expect(described_class.fuzzy_find(1)).to eq(user)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "finds by mention name" do
|
80
|
+
expect(described_class.fuzzy_find("carlthepug")).to eq(user)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "finds by name" do
|
84
|
+
expect(described_class.fuzzy_find("Carl the Pug")).to eq(user)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "finds by partial mention name" do
|
88
|
+
expect(described_class.fuzzy_find("Carl")).to eq(user)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
37
92
|
describe "#save" do
|
38
|
-
subject { described_class.new(1, name: "Carl") }
|
93
|
+
subject { described_class.new(1, name: "Carl", mention_name: "carlthepug") }
|
39
94
|
|
40
95
|
it "saves an ID to name mapping for the user in Redis" do
|
41
96
|
subject.save
|
42
|
-
expect(described_class.redis.hgetall("id:1")).to
|
97
|
+
expect(described_class.redis.hgetall("id:1")).to include("name" => "Carl")
|
43
98
|
end
|
44
99
|
|
45
100
|
it "saves a name to ID mapping for the user in Redis" do
|
46
101
|
subject.save
|
47
102
|
expect(described_class.redis.get("name:Carl")).to eq("1")
|
48
103
|
end
|
104
|
+
|
105
|
+
it "saves a mention name to ID mapping for the user in Redis" do
|
106
|
+
subject.save
|
107
|
+
expect(described_class.redis.get("mention_name:carlthepug")).to eq("1")
|
108
|
+
end
|
49
109
|
end
|
50
110
|
|
51
111
|
describe "#==" do
|
data/spec/lita_spec.rb
CHANGED
@@ -13,6 +13,43 @@ describe Lita do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
describe ".load_locales" do
|
17
|
+
let(:load_path) do
|
18
|
+
load_path = double("Array")
|
19
|
+
allow(load_path).to receive(:concat)
|
20
|
+
load_path
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:new_locales) { %w(foo bar) }
|
24
|
+
|
25
|
+
before do
|
26
|
+
allow(I18n).to receive(:load_path).and_return(load_path)
|
27
|
+
allow(I18n).to receive(:reload!)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "appends the locale files to I18n.load_path" do
|
31
|
+
expect(I18n.load_path).to receive(:concat).with(new_locales)
|
32
|
+
described_class.load_locales(new_locales)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "reloads I18n" do
|
36
|
+
expect(I18n).to receive(:reload!)
|
37
|
+
described_class.load_locales(new_locales)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "wraps single paths in an array" do
|
41
|
+
expect(I18n.load_path).to receive(:concat).with(["foo"])
|
42
|
+
described_class.load_locales("foo")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe ".locale=" do
|
47
|
+
it "sets I18n.locale to the normalized locale" do
|
48
|
+
expect(I18n).to receive(:locale=).with("es-MX.UTF-8")
|
49
|
+
described_class.locale = "es_MX.UTF-8"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
16
53
|
describe ".redis" do
|
17
54
|
it "memoizes a Redis::Namespace" do
|
18
55
|
expect(described_class.redis).to respond_to(:namespace)
|
data/spec/spec_helper.rb
CHANGED
@@ -8,4 +8,15 @@ SimpleCov.start { add_filter "/spec/" }
|
|
8
8
|
|
9
9
|
require "pry"
|
10
10
|
require "lita"
|
11
|
+
require "lita/cli"
|
11
12
|
require "lita/rspec"
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.mock_with :rspec do |mocks_config|
|
16
|
+
mocks_config.verify_doubled_constant_names = true
|
17
|
+
# Enable config option this when a new rspec-mocks beta including this patch is released:
|
18
|
+
# https://github.com/rspec/rspec-mocks/pull/466
|
19
|
+
#
|
20
|
+
# mocks_config.verify_partial_doubles = true
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
en:
|
2
|
+
lita:
|
3
|
+
adapters:
|
4
|
+
shell:
|
5
|
+
startup_message: Type "exit" or "quit" to end the session.
|
6
|
+
handlers:
|
7
|
+
authorization:
|
8
|
+
help:
|
9
|
+
add_key: auth add USER GROUP
|
10
|
+
add_value: Add USER to authorization group GROUP. Requires admin privileges.
|
11
|
+
remove_key: auth remove USER GROUP
|
12
|
+
remove_value: Remove USER from authorization group GROUP. Requires admin privileges.
|
13
|
+
list_key: "auth list [GROUP]"
|
14
|
+
list_value: >-
|
15
|
+
List authorization groups and the users in them. If GROUP is supplied,
|
16
|
+
only lists that group.
|
17
|
+
user_added: "%{user} was added to %{group}."
|
18
|
+
user_already_in: "%{user} was already in %{group}."
|
19
|
+
user_removed: "%{user} was removed from %{group}."
|
20
|
+
user_not_in: "%{user} was not in %{group}."
|
21
|
+
empty_state: There are no authorization groups yet.
|
22
|
+
empty_state_group: "There is no authorization group named %{group}."
|
23
|
+
format: "Format"
|
24
|
+
admin_management: Administrators can only be managed via Lita config.
|
25
|
+
no_user_found: 'No user was found with the identifier "%{identifier}".'
|
26
|
+
help:
|
27
|
+
help:
|
28
|
+
help_value: Lists help information for terms and command the robot will respond to.
|
29
|
+
help_command_key: help COMMAND
|
30
|
+
help_command_value: Lists help information for terms or commands that begin with COMMAND.
|
31
|
+
info:
|
32
|
+
help:
|
33
|
+
info_value: Replies with the current version of Lita.
|
34
|
+
room:
|
35
|
+
help:
|
36
|
+
join_key: join ROOM_ID
|
37
|
+
join_value: Makes the robot join the room with room ID ROOM_ID.
|
38
|
+
part_key: part ROOM_ID
|
39
|
+
part_value: Makes the robot part from the room with room ID ROOM_ID.
|
40
|
+
adapter:
|
41
|
+
name_required: Adapters that are anonymous classes must define self.name.
|
42
|
+
method_not_implemented: "This adapter has not implemented #%{method}."
|
43
|
+
missing_configs: "The following keys are required on config.adapter: %{configs}"
|
44
|
+
cli:
|
45
|
+
no_gemfile_warning: >-
|
46
|
+
The default command "start" must be run inside a Lita project. Try running `lita new` to
|
47
|
+
generate a new Lita project or `lita help` to see all commands.
|
48
|
+
travis_question: Do you want to test your plugin on Travis CI?
|
49
|
+
coveralls_question: |-
|
50
|
+
Do you want to generate code coverage information with SimpleCov and Coveralls.io?
|
51
|
+
config:
|
52
|
+
exception: |
|
53
|
+
Lita configuration file could not be processed. The exception was:
|
54
|
+
%{message}
|
55
|
+
Full backtrace:
|
56
|
+
%{backtrace}
|
57
|
+
daemon:
|
58
|
+
pid_exists: >-
|
59
|
+
PID file exists at %{path}. Lita may already be running. Kill the existing process or
|
60
|
+
remove the PID file and then start Lita.
|
61
|
+
kill_failure: "Failed to kill existing Lita process %{pid}."
|
62
|
+
handler:
|
63
|
+
name_required: Handlers that are anonymous classes must define self.name.
|
64
|
+
dispatch: "Dispatching message to %{handler}#%{method}."
|
65
|
+
exception: |
|
66
|
+
%{handler} crashed. The exception was:
|
67
|
+
%{message}
|
68
|
+
Full backtrace:
|
69
|
+
%{backtrace}
|
70
|
+
robot:
|
71
|
+
unknown_adapter: "Unknown adapter: :%{adapter}."
|
72
|
+
rspec:
|
73
|
+
full_suite_required: Lita::RSpec requires both RSpec::Mocks and RSpec::Expectations.
|
74
|
+
mocks_expect_syntax_required: RSpec::Mocks 2.14 or greater is required to use Lita::RSpec.
|
75
|
+
route_failure: |-
|
76
|
+
Expected message "%{message}" to route to :%{route}, but didn't.
|
77
|
+
negative_route_failure: |-
|
78
|
+
Expected message "%{message}" not to route to :%{route}, but did.
|
79
|
+
http_route_failure: |-
|
80
|
+
Expected request "%{method} %{path}" to route to :%{route}, but didn't.
|
81
|
+
negative_http_route_failure: |-
|
82
|
+
Expected request "%{method} %{path}" not to route to :%{route}, but did.
|
83
|
+
event_subscription_failure: |-
|
84
|
+
Expected triggering event "%{event}" to invoke :%{route}, but didn't.
|
85
|
+
negative_event_subscription_failure: |-
|
86
|
+
Expected triggering event "%{event}" not to invoke :%{route}, but did.
|
87
|
+
source:
|
88
|
+
user_or_room_required: Either a user or a room is required.
|
89
|
+
user:
|
90
|
+
find_deprecated: Lita::User.find will be removed in Lita 4.0. Use Lita::User.create instead.
|
data/templates/plugin/Rakefile
CHANGED