lita 1.1.2 → 2.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/README.md +202 -45
- data/lib/lita.rb +45 -24
- data/lib/lita/adapter.rb +35 -0
- data/lib/lita/adapters/shell.rb +14 -3
- data/lib/lita/authorization.rb +24 -0
- data/lib/lita/cli.rb +1 -0
- data/lib/lita/config.rb +52 -19
- data/lib/lita/handler.rb +100 -36
- data/lib/lita/handlers/authorization.rb +38 -27
- data/lib/lita/handlers/help.rb +25 -22
- data/lib/lita/handlers/web.rb +25 -0
- data/lib/lita/http_route.rb +64 -0
- data/lib/lita/logger.rb +34 -0
- data/lib/lita/message.rb +41 -7
- data/lib/lita/rack_app_builder.rb +110 -0
- data/lib/lita/response.rb +30 -0
- data/lib/lita/robot.rb +56 -1
- data/lib/lita/rspec.rb +23 -50
- data/lib/lita/rspec/handler.rb +168 -0
- data/lib/lita/source.rb +19 -1
- data/lib/lita/user.rb +37 -1
- data/lib/lita/util.rb +26 -0
- data/lib/lita/version.rb +2 -1
- data/lita.gemspec +5 -0
- data/spec/lita/adapters/shell_spec.rb +12 -4
- data/spec/lita/config_spec.rb +18 -2
- data/spec/lita/handler_spec.rb +43 -46
- data/spec/lita/handlers/authorization_spec.rb +24 -31
- data/spec/lita/handlers/help_spec.rb +10 -8
- data/spec/lita/handlers/web_spec.rb +19 -0
- data/spec/lita/logger_spec.rb +26 -0
- data/spec/lita/message_spec.rb +16 -11
- data/spec/lita/robot_spec.rb +25 -2
- data/spec/lita/rspec_spec.rb +32 -20
- data/spec/lita/util_spec.rb +9 -0
- data/spec/lita_spec.rb +0 -51
- data/spec/spec_helper.rb +2 -1
- metadata +85 -3
- data/CHANGELOG.md +0 -21
data/spec/lita/config_spec.rb
CHANGED
@@ -16,8 +16,24 @@ describe Lita::Config do
|
|
16
16
|
|
17
17
|
describe ".default_config" do
|
18
18
|
it "has predefined values for certain keys" do
|
19
|
-
|
20
|
-
expect(
|
19
|
+
default_config = described_class.default_config
|
20
|
+
expect(default_config.robot.name).to eq("Lita")
|
21
|
+
expect(default_config.robot.adapter).to eq(:shell)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "loads configuration from registered handlers" do
|
25
|
+
handler = Class.new(Lita::Handler) do
|
26
|
+
def self.default_config(handler_config)
|
27
|
+
handler_config.bar = :baz
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.name
|
31
|
+
"Lita::Handlers::Foo"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
allow(Lita).to receive(:handlers).and_return([handler])
|
35
|
+
default_config = described_class.default_config
|
36
|
+
expect(default_config.handlers.foo.bar).to eq(:baz)
|
21
37
|
end
|
22
38
|
end
|
23
39
|
|
data/spec/lita/handler_spec.rb
CHANGED
@@ -1,40 +1,33 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Lita::Handler do
|
4
|
-
let(:robot)
|
5
|
-
|
6
|
-
allow(robot).to receive(:name).and_return("Lita")
|
7
|
-
robot
|
8
|
-
end
|
4
|
+
let(:robot) { double("Lita::Robot", name: "Lita") }
|
5
|
+
let(:user) { double("Lita::User") }
|
9
6
|
|
10
7
|
let(:message) do
|
11
|
-
message = double("Message")
|
12
|
-
allow(message).to receive(:
|
13
|
-
allow(message).to receive(:command?).and_return(false)
|
14
|
-
allow(message).to receive(:source).and_return(source)
|
15
|
-
allow(message).to receive(:user).and_return(user)
|
8
|
+
message = double("Lita::Message", user: user, command?: false)
|
9
|
+
allow(message).to receive(:match)
|
16
10
|
message
|
17
11
|
end
|
18
12
|
|
19
|
-
let(:matches) { double("MatchData") }
|
20
|
-
|
21
|
-
let(:source) { double("Source") }
|
22
|
-
|
23
|
-
let(:user) { double("User") }
|
24
|
-
|
25
13
|
let(:handler_class) do
|
26
14
|
Class.new(described_class) do
|
27
|
-
route(/\w{3}/,
|
28
|
-
route(/\w{4}/,
|
29
|
-
route(/secret/,
|
15
|
+
route(/\w{3}/, :foo)
|
16
|
+
route(/\w{4}/, :blah, command: true)
|
17
|
+
route(/secret/, :secret, restrict_to: :admins)
|
18
|
+
|
19
|
+
http.get "web", :web
|
20
|
+
|
21
|
+
def foo(response)
|
22
|
+
end
|
30
23
|
|
31
|
-
def
|
24
|
+
def blah(response)
|
32
25
|
end
|
33
26
|
|
34
|
-
def
|
27
|
+
def secret(response)
|
35
28
|
end
|
36
29
|
|
37
|
-
def
|
30
|
+
def web(request, response)
|
38
31
|
end
|
39
32
|
|
40
33
|
def self.name
|
@@ -43,7 +36,7 @@ describe Lita::Handler do
|
|
43
36
|
end
|
44
37
|
end
|
45
38
|
|
46
|
-
subject { described_class.new(robot
|
39
|
+
subject { described_class.new(robot) }
|
47
40
|
|
48
41
|
describe ".dispatch" do
|
49
42
|
it "routes a matching message to the supplied method" do
|
@@ -94,38 +87,42 @@ describe Lita::Handler do
|
|
94
87
|
end
|
95
88
|
end
|
96
89
|
|
97
|
-
describe "
|
98
|
-
it "
|
99
|
-
|
100
|
-
|
90
|
+
describe ".namespace" do
|
91
|
+
it "provides a snake cased namespace for the handler" do
|
92
|
+
handler_class = Class.new(described_class) do
|
93
|
+
def self.name
|
94
|
+
"Lita::Handlers::FooBarBaz"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
expect(handler_class.namespace).to eq("foo_bar_baz")
|
101
98
|
end
|
102
|
-
end
|
103
99
|
|
104
|
-
|
105
|
-
|
106
|
-
expect
|
107
|
-
subject.command?
|
100
|
+
it "raises an exception if the handler doesn't define self.name" do
|
101
|
+
handler_class = Class.new(described_class)
|
102
|
+
expect { handler_class.namespace }.to raise_error
|
108
103
|
end
|
109
104
|
end
|
110
105
|
|
111
|
-
describe "#
|
112
|
-
it "
|
113
|
-
expect(
|
114
|
-
subject.message_body
|
106
|
+
describe "#http" do
|
107
|
+
it "returns a Faraday connection" do
|
108
|
+
expect(subject.http).to be_a(Faraday::Connection)
|
115
109
|
end
|
116
|
-
end
|
117
110
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
111
|
+
it "sets a default user agent" do
|
112
|
+
expect(subject.http.headers["User-Agent"]).to eq("Lita v#{Lita::VERSION}")
|
113
|
+
end
|
114
|
+
|
115
|
+
it "merges in user-supplied options" do
|
116
|
+
connection = subject.http(headers: {
|
117
|
+
"User-Agent" => "Foo", "X-Bar" => "Baz"
|
118
|
+
})
|
119
|
+
expect(connection.headers["User-Agent"]).to eq("Foo")
|
120
|
+
expect(connection.headers["X-Bar"]).to eq("Baz")
|
122
121
|
end
|
123
|
-
end
|
124
122
|
|
125
|
-
|
126
|
-
|
127
|
-
expect(
|
128
|
-
subject.scan
|
123
|
+
it "passes blocks on to Faraday" do
|
124
|
+
connection = subject.http { |builder| builder.response :logger }
|
125
|
+
expect(connection.builder.handlers).to include(Faraday::Response::Logger)
|
129
126
|
end
|
130
127
|
end
|
131
128
|
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Lita::Handlers::Authorization,
|
3
|
+
describe Lita::Handlers::Authorization, lita_handler: true do
|
4
4
|
before do
|
5
|
-
allow(robot).to receive(:send_messages)
|
6
5
|
allow(Lita::Authorization).to receive(:user_is_admin?).with(
|
7
6
|
user
|
8
7
|
).and_return(true)
|
@@ -10,39 +9,33 @@ describe Lita::Handlers::Authorization, lita: true do
|
|
10
9
|
|
11
10
|
let(:target_user) { double("Lita::User", id: "1", name: "Carl") }
|
12
11
|
|
13
|
-
it {
|
14
|
-
it {
|
15
|
-
it {
|
16
|
-
it {
|
17
|
-
|
18
|
-
describe ".help" do
|
19
|
-
it "returns a hash of command help" do
|
20
|
-
expect(described_class.help).to be_a(Hash)
|
21
|
-
end
|
22
|
-
end
|
12
|
+
it { routes_command("auth add foo bar").to(:add) }
|
13
|
+
it { routes_command("auth add foo@bar.com baz").to(:add) }
|
14
|
+
it { routes_command("auth remove foo bar").to(:remove) }
|
15
|
+
it { routes_command("auth remove foo@bar.com baz").to(:remove) }
|
23
16
|
|
24
17
|
describe "#add" do
|
25
18
|
it "replies with the proper format if the require commands are missing" do
|
26
|
-
|
27
|
-
|
19
|
+
send_command("auth add foo")
|
20
|
+
expect(replies.last).to match(/^Format:/)
|
28
21
|
end
|
29
22
|
|
30
23
|
it "replies with a warning if target user is not known" do
|
31
|
-
|
32
|
-
|
24
|
+
send_command("auth add foo bar")
|
25
|
+
expect(replies.last).to match(/No user was found/)
|
33
26
|
end
|
34
27
|
|
35
28
|
it "replies with success if a valid user and group were supplied" do
|
36
29
|
allow(Lita::User).to receive(:find_by_id).and_return(target_user)
|
37
|
-
|
38
|
-
|
30
|
+
send_command("auth add foo bar")
|
31
|
+
expect(replies.last).to eq("#{target_user.name} was added to bar.")
|
39
32
|
end
|
40
33
|
|
41
34
|
it "replies with a warning if the user was already in the group" do
|
42
35
|
allow(Lita::User).to receive(:find_by_id).and_return(target_user)
|
43
|
-
|
44
|
-
|
45
|
-
|
36
|
+
send_command("auth add foo bar")
|
37
|
+
send_command("auth add foo bar")
|
38
|
+
expect(replies.last).to eq("#{target_user.name} was already in bar.")
|
46
39
|
end
|
47
40
|
|
48
41
|
it "replies with a warning if the requesting user is not an admin" do
|
@@ -50,34 +43,34 @@ describe Lita::Handlers::Authorization, lita: true do
|
|
50
43
|
allow(Lita::Authorization).to receive(:user_is_admin?).with(
|
51
44
|
user
|
52
45
|
).and_return(false)
|
53
|
-
|
54
|
-
|
46
|
+
send_command("auth add foo bar")
|
47
|
+
expect(replies.last).to match(/Only administrators can add/)
|
55
48
|
end
|
56
49
|
end
|
57
50
|
|
58
51
|
describe "#remove" do
|
59
52
|
before do
|
60
53
|
allow(Lita::User).to receive(:find_by_id).and_return(target_user)
|
61
|
-
|
54
|
+
send_command("auth add foo bar")
|
62
55
|
end
|
63
56
|
|
64
57
|
it "replies with success if a valid user and group were supplied" do
|
65
|
-
|
66
|
-
|
58
|
+
send_command("auth remove foo bar")
|
59
|
+
expect(replies.last).to eq("#{target_user.name} was removed from bar.")
|
67
60
|
end
|
68
61
|
|
69
62
|
it "replies with a warning if the user was already in the group" do
|
70
|
-
|
71
|
-
|
72
|
-
|
63
|
+
send_command("auth remove foo bar")
|
64
|
+
send_command("auth remove foo bar")
|
65
|
+
expect(replies.last).to eq("#{target_user.name} was not in bar.")
|
73
66
|
end
|
74
67
|
|
75
68
|
it "replies with a warning if the requesting user is not an admin" do
|
76
69
|
allow(Lita::Authorization).to receive(:user_is_admin?).with(
|
77
70
|
user
|
78
71
|
).and_return(false)
|
79
|
-
|
80
|
-
|
72
|
+
send_command("auth remove foo bar")
|
73
|
+
expect(replies.last).to match(/Only administrators can remove/)
|
81
74
|
end
|
82
75
|
end
|
83
76
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Lita::Handlers::Help,
|
4
|
-
it {
|
5
|
-
it {
|
3
|
+
describe Lita::Handlers::Help, lita_handler: true do
|
4
|
+
it { routes_command("help").to(:help) }
|
5
|
+
it { routes_command("help foo").to(:help) }
|
6
6
|
|
7
7
|
describe "#help" do
|
8
8
|
it "sends help information for all commands" do
|
9
|
-
|
10
|
-
|
9
|
+
send_command("help")
|
10
|
+
expect(replies.last).to match(
|
11
|
+
/#{robot.mention_name}: help.+#{robot.mention_name}: help COMMAND/m
|
12
|
+
)
|
11
13
|
end
|
12
14
|
|
13
15
|
it "sends help information for commands starting with COMMAND" do
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
send_command("help help COMMAND")
|
17
|
+
expect(replies.last).to match(/help COMMAND - Lists/)
|
18
|
+
expect(replies.last).not_to match(/help - Lists/)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Lita::Handlers::Web, lita_handler: true do
|
4
|
+
it { routes_http(:get, "/lita/info").to(:info) }
|
5
|
+
it { doesnt_route_http(:post, "/lita/info").to(:info) }
|
6
|
+
|
7
|
+
let(:request) { double("Rack::Request") }
|
8
|
+
let(:response) { Rack::Response.new }
|
9
|
+
|
10
|
+
describe "#info" do
|
11
|
+
it "returns JSON with info about the running robot" do
|
12
|
+
subject.info(request, response)
|
13
|
+
expect(response.headers["Content-Type"]).to eq("application/json")
|
14
|
+
expect(response.body.join).to include(
|
15
|
+
%{"lita_version":"#{Lita::VERSION}"}
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Lita::Logger do
|
4
|
+
it "uses a custom log level" do
|
5
|
+
logger = described_class.get_logger(:debug)
|
6
|
+
expect(logger.level).to eq(Logger::DEBUG)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "uses the info level if the config is nil" do
|
10
|
+
logger = described_class.get_logger(nil)
|
11
|
+
expect(logger.level).to eq(Logger::INFO)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "uses the info level if the config level is invalid" do
|
15
|
+
logger = described_class.get_logger(:foo)
|
16
|
+
expect(logger.level).to eq(Logger::INFO)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "logs messages with a custom format" do
|
20
|
+
stderr = StringIO.new
|
21
|
+
stub_const("STDERR", stderr)
|
22
|
+
logger = described_class.get_logger(:debug)
|
23
|
+
logger.fatal "foo"
|
24
|
+
expect(stderr.string).to match(%r{^\[.+\] FATAL: foo$})
|
25
|
+
end
|
26
|
+
end
|
data/spec/lita/message_spec.rb
CHANGED
@@ -11,10 +11,6 @@ describe Lita::Message do
|
|
11
11
|
expect(subject.body).to eq("Hello")
|
12
12
|
end
|
13
13
|
|
14
|
-
it "aliases #body with #message" do
|
15
|
-
expect(subject.message).to eq("Hello")
|
16
|
-
end
|
17
|
-
|
18
14
|
it "has a source" do
|
19
15
|
expect(subject.source).to eq("Carl")
|
20
16
|
end
|
@@ -48,15 +44,17 @@ describe Lita::Message do
|
|
48
44
|
expect(subject).to be_a_command
|
49
45
|
end
|
50
46
|
|
51
|
-
it "is
|
52
|
-
|
47
|
+
it "is true when the Robot's name is capitalized differently" do
|
48
|
+
subject = described_class.new(
|
49
|
+
robot,
|
50
|
+
"#{robot.mention_name.upcase}: hello",
|
51
|
+
"Carl"
|
52
|
+
)
|
53
|
+
expect(subject).to be_a_command
|
53
54
|
end
|
54
|
-
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
expect(subject.body).to receive(:scan)
|
59
|
-
subject.scan
|
56
|
+
it "is false when the message is not addressed to the Robot" do
|
57
|
+
expect(subject).not_to be_a_command
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
@@ -66,4 +64,11 @@ describe Lita::Message do
|
|
66
64
|
subject.user
|
67
65
|
end
|
68
66
|
end
|
67
|
+
|
68
|
+
describe "#reply" do
|
69
|
+
it "sends strings back to the source through the robot" do
|
70
|
+
expect(robot).to receive(:send_messages).with("Carl", "foo", "bar")
|
71
|
+
subject.reply("foo", "bar")
|
72
|
+
end
|
73
|
+
end
|
69
74
|
end
|
data/spec/lita/robot_spec.rb
CHANGED
@@ -10,8 +10,8 @@ describe Lita::Robot do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
describe "#receive" do
|
13
|
-
let(:handler1) { double("Handler 1") }
|
14
|
-
let(:handler2) { double("Handler 2") }
|
13
|
+
let(:handler1) { double("Handler 1").as_null_object }
|
14
|
+
let(:handler2) { double("Handler 2").as_null_object }
|
15
15
|
|
16
16
|
it "dispatches messages to every registered handler" do
|
17
17
|
allow(Lita).to receive(:handlers).and_return([handler1, handler2])
|
@@ -22,11 +22,34 @@ describe Lita::Robot do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
describe "#run" do
|
25
|
+
let(:thread) { double("Thread", :abort_on_exception= => true, join: nil) }
|
26
|
+
|
27
|
+
before do
|
28
|
+
allow_any_instance_of(Lita::Adapters::Shell).to receive(:run)
|
29
|
+
allow_any_instance_of(Thin::Server).to receive(:start)
|
30
|
+
|
31
|
+
allow(Thread).to receive(:new) do |&block|
|
32
|
+
block.call
|
33
|
+
thread
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
25
37
|
it "starts the adapter" do
|
26
38
|
expect_any_instance_of(Lita::Adapters::Shell).to receive(:run)
|
27
39
|
subject.run
|
28
40
|
end
|
29
41
|
|
42
|
+
it "starts the web server" do
|
43
|
+
expect_any_instance_of(Thin::Server).to receive(:start)
|
44
|
+
subject.run
|
45
|
+
end
|
46
|
+
|
47
|
+
it "doesn't silence thin if config.http.debug is true" do
|
48
|
+
Lita.config.http.debug = true
|
49
|
+
expect_any_instance_of(Thin::Server).not_to receive(:silent=)
|
50
|
+
subject.run
|
51
|
+
end
|
52
|
+
|
30
53
|
it "rescues interrupts and calls #shut_down" do
|
31
54
|
allow_any_instance_of(
|
32
55
|
Lita::Adapters::Shell
|
data/spec/lita/rspec_spec.rb
CHANGED
@@ -1,15 +1,24 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
handler_class = Class.new(Lita::Handler) do
|
4
|
-
route(
|
5
|
-
route(
|
4
|
+
route(/^\w{3}$/, :foo)
|
5
|
+
route(/^\w{4}$/, :blah, command: true)
|
6
|
+
route("restricted", :restricted, restrict_to: :some_group)
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
http.get "web", :web
|
9
|
+
|
10
|
+
def foo(response)
|
11
|
+
response.reply "baz"
|
12
|
+
end
|
13
|
+
|
14
|
+
def blah(response)
|
15
|
+
response.reply "bongo", "wongo"
|
16
|
+
end
|
17
|
+
|
18
|
+
def restricted(response)
|
9
19
|
end
|
10
20
|
|
11
|
-
def
|
12
|
-
reply "bongo", "wongo"
|
21
|
+
def web(request, response)
|
13
22
|
end
|
14
23
|
|
15
24
|
def self.name
|
@@ -17,33 +26,36 @@ handler_class = Class.new(Lita::Handler) do
|
|
17
26
|
end
|
18
27
|
end
|
19
28
|
|
20
|
-
describe handler_class,
|
29
|
+
describe handler_class, lita_handler: true do
|
21
30
|
it { routes("foo").to(:foo) }
|
22
|
-
it {
|
31
|
+
it { routes_command("blah").to(:blah) }
|
23
32
|
it { doesnt_route("blah").to(:blah) }
|
24
33
|
it { does_not_route("blah").to(:blah) }
|
34
|
+
it { doesnt_route_command("yo").to(:foo) }
|
35
|
+
it { does_not_route_command("yo").to(:foo) }
|
36
|
+
it { routes("restricted").to(:restricted) }
|
37
|
+
it { routes_http(:get, "web").to(:web) }
|
38
|
+
it { doesnt_route_http(:post, "web").to(:web) }
|
25
39
|
|
26
40
|
describe "#foo" do
|
27
41
|
it "replies with baz" do
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
it "doesn't reply with blam" do
|
33
|
-
expect_no_reply("blam")
|
34
|
-
send_test_message("foo")
|
42
|
+
send_message("foo")
|
43
|
+
expect(replies).to eq(["baz"])
|
35
44
|
end
|
36
45
|
end
|
37
46
|
|
38
47
|
describe "#blah" do
|
39
48
|
it "replies with bongo and wongo" do
|
40
|
-
|
41
|
-
|
49
|
+
send_command("blah")
|
50
|
+
expect(replies).to eq(["bongo", "wongo"])
|
42
51
|
end
|
52
|
+
end
|
43
53
|
|
44
|
-
|
45
|
-
|
46
|
-
|
54
|
+
it "allows the sending user to be specified" do
|
55
|
+
another_user = Lita::User.create(2, name: "Another User")
|
56
|
+
expect(robot).to receive(:receive) do |message|
|
57
|
+
expect(message.source.user).to eq(another_user)
|
47
58
|
end
|
59
|
+
send_message("foo", as: another_user)
|
48
60
|
end
|
49
61
|
end
|