lita 2.7.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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