boty 0.0.17 → 0.0.17.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/boty.gemspec +1 -1
- data/lib/boty/version.rb +1 -1
- data/spec/boty/bot_spec.rb +419 -0
- data/spec/boty/cli_spec.rb +87 -0
- data/spec/boty/logger_spec.rb +32 -0
- data/spec/boty/message_spec.rb +32 -0
- data/spec/boty/rspec_spec.rb +36 -0
- data/spec/boty/session_spec.rb +70 -0
- data/spec/boty/slack/chat_spec.rb +73 -0
- data/spec/boty/slack/im_spec.rb +34 -0
- data/spec/boty/slack/rtm_spec.rb +20 -0
- data/spec/boty/slack/url_spec.rb +71 -0
- data/spec/boty/slack/users_spec.rb +44 -0
- data/spec/happy_path_spec.rb +88 -0
- data/spec/script/i18n_spec.rb +22 -0
- data/spec/script/knows_spec.rb +18 -0
- data/spec/script/pug_spec.rb +53 -0
- data/spec/script/remember_spec.rb +43 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/em_support.rb +13 -0
- data/spec/support/fakefs_support.rb +13 -0
- data/spec/support/faraday_support.rb +15 -0
- data/spec/support/faye_support.rb +34 -0
- data/spec/support/file_system_matchers.rb +19 -0
- data/spec/support/session_support.rb +31 -0
- data/spec/support/slack_support.rb +28 -0
- data/spec/support/template_project_support.rb +44 -0
- data/spec/support/thor_support.rb +21 -0
- metadata +27 -1
@@ -0,0 +1,87 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "boty/cli"
|
3
|
+
|
4
|
+
module Boty
|
5
|
+
RSpec.describe CLI, :thor do
|
6
|
+
subject(:cli) { described_class.new }
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
FileUtils.mkdir_p "tmp" if !Dir.exists? "tmp"
|
10
|
+
FileUtils.chdir "tmp"
|
11
|
+
end
|
12
|
+
|
13
|
+
before do
|
14
|
+
FileUtils.rm_rf "nice_bot" if Dir.exists? "nice_bot"
|
15
|
+
|
16
|
+
allow(cli).to receive(:ask).
|
17
|
+
and_return ENV["SLACK_COMPANY"], ENV["SLACK_BOT_API_TOKEN"]
|
18
|
+
|
19
|
+
allow(cli).to receive(:run)
|
20
|
+
end
|
21
|
+
|
22
|
+
after(:all) do
|
23
|
+
FileUtils.rm_rf "nice_bot" if Dir.exists? "nice_bot"
|
24
|
+
FileUtils.chdir "../"
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#new PROJECT" do
|
28
|
+
def create_nice_bot
|
29
|
+
capture(:stdout) do
|
30
|
+
cli.new "nice_bot"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "creates a directory named after the PROJECT" do
|
35
|
+
expect { create_nice_bot }.to create_directory "nice_bot"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "creates the executable" do
|
39
|
+
expect { create_nice_bot }.to create_file "nice_bot/bot"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "creates the empty dir for scripts" do
|
43
|
+
expect { create_nice_bot }.to create_directory "nice_bot/script"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "creates the empty dir for locales" do
|
47
|
+
expect { create_nice_bot }.to create_directory "nice_bot/locale"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "creates the empty dir for bot development" do
|
51
|
+
expect { create_nice_bot }.to create_directory "nice_bot/app"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "creates the Gemfile" do
|
55
|
+
expect { create_nice_bot }.to create_file "nice_bot/Gemfile"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "creates the Procfile" do
|
59
|
+
expect { create_nice_bot }.to create_file "nice_bot/Procfile"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "creates the README.md" do
|
63
|
+
expect { create_nice_bot }.to create_file "nice_bot/README.md"
|
64
|
+
end
|
65
|
+
|
66
|
+
context "/spec" do
|
67
|
+
it "creates the spec/ dir" do
|
68
|
+
expect { create_nice_bot }.to create_directory "nice_bot/spec"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "creates the .rspec file" do
|
72
|
+
expect { create_nice_bot }.to create_file "nice_bot/.rspec"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it "turns the ./bot an executable file" do
|
77
|
+
expect(cli).to run "chmod +x bot"
|
78
|
+
create_nice_bot
|
79
|
+
end
|
80
|
+
|
81
|
+
it "runs bundle install after create the project" do
|
82
|
+
expect(cli).to run "bundle install"
|
83
|
+
create_nice_bot
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Boty
|
2
|
+
RSpec.describe Logger do
|
3
|
+
class Client; include Logger end
|
4
|
+
|
5
|
+
let(:logger) { Boty::Logger }
|
6
|
+
let(:client) { Client.new }
|
7
|
+
|
8
|
+
describe ".adapter" do
|
9
|
+
it "changes the internal logger representation" do
|
10
|
+
memory_logger = Boty::Logger::Memory.new
|
11
|
+
logger.adapter = memory_logger
|
12
|
+
expect(memory_logger).to receive(:info).with "hello"
|
13
|
+
|
14
|
+
client.logger.info "hello"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe Logger::Memory do
|
19
|
+
subject(:adapter) { described_class.new }
|
20
|
+
|
21
|
+
before do
|
22
|
+
logger.adapter = adapter
|
23
|
+
end
|
24
|
+
|
25
|
+
it "stores the logs in memory" do
|
26
|
+
client.logger.info "hello"
|
27
|
+
|
28
|
+
expect(adapter.logs.last).to eq "hello"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Boty
|
2
|
+
RSpec.describe Message, :users do
|
3
|
+
subject(:message) { described_class.new message_json }
|
4
|
+
|
5
|
+
let(:user_id) { "U7777" }
|
6
|
+
let(:user_name) { "julian" }
|
7
|
+
|
8
|
+
let(:message_json) {{
|
9
|
+
"type" => "message",
|
10
|
+
"text" => "omg lol bbq",
|
11
|
+
"user" => "U7777",
|
12
|
+
"channel" => "333",
|
13
|
+
"ts" => "1234",
|
14
|
+
"team" => "3452"
|
15
|
+
}}
|
16
|
+
|
17
|
+
it "uses Slack.users.info to create a User instance" do
|
18
|
+
expect(message.user.id).to eq "U7777"
|
19
|
+
expect(message.user.name).to eq "julian"
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#from?" do
|
23
|
+
it "returns true if the param is the message author" do
|
24
|
+
expect(message.from? "U7777").to eq true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns true if the param `respond_to? :id` returning the message author" do
|
28
|
+
expect(message.from? OpenStruct.new(id: "U7777")).to eq true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "boty/rspec"
|
2
|
+
|
3
|
+
module Boty
|
4
|
+
::RSpec.describe Boty::RSpec::Bot do
|
5
|
+
include described_class
|
6
|
+
|
7
|
+
context "bot[Boty::Bot] instance" do
|
8
|
+
it "includes a `bot` instance in the example scope" do
|
9
|
+
expect(bot).to be_a Boty::ScriptDSL
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "have_responded matcher" do
|
14
|
+
it "provides a custom matcher to check against bot responses" do
|
15
|
+
expect(self).to respond_to(:have_responded)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "makes `Bot#say` work with the custom `have_responded` matcher" do
|
19
|
+
bot.say "something"
|
20
|
+
expect(bot).to have_responded "something"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "clears up the `Bot#_response` after check by matcher" do
|
24
|
+
bot.say "something"
|
25
|
+
expect(bot).to have_responded "something"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "helpers" do
|
30
|
+
it "includes #message_event to fire `data['type'] = 'message' events" do
|
31
|
+
expect(@_bot).to receive(:event).with "type" => "message", "text" => "omg"
|
32
|
+
message "omg"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Boty
|
2
|
+
RSpec.describe Session do
|
3
|
+
subject(:session) { described_class.new }
|
4
|
+
|
5
|
+
let(:rtm_start_json_response) {
|
6
|
+
JSON.parse '{
|
7
|
+
"url": "ws://example.org/slack/sse/url",
|
8
|
+
"self": {
|
9
|
+
"id": "1234"
|
10
|
+
}
|
11
|
+
}'
|
12
|
+
}
|
13
|
+
|
14
|
+
before do
|
15
|
+
allow(Slack.rtm).to receive(:start).and_return rtm_start_json_response
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#start", :em, :faye do
|
19
|
+
specify do
|
20
|
+
expect { |b| session.start(&b) }.to yield_control
|
21
|
+
end
|
22
|
+
|
23
|
+
it "logs in (request session url)" do
|
24
|
+
expect(Slack.rtm).to receive(:start).and_return rtm_start_json_response
|
25
|
+
|
26
|
+
session.start
|
27
|
+
end
|
28
|
+
|
29
|
+
it "creates the event loop" do
|
30
|
+
expect(EM).to receive(:run)
|
31
|
+
|
32
|
+
session.start
|
33
|
+
end
|
34
|
+
|
35
|
+
it "intializes the sse client with the session url" do
|
36
|
+
expect(Faye::WebSocket::Client).to receive(:new).
|
37
|
+
with("ws://example.org/slack/sse/url")
|
38
|
+
|
39
|
+
session.start
|
40
|
+
end
|
41
|
+
|
42
|
+
it "repasses `:message` event to `bot#event`" do
|
43
|
+
data = '{
|
44
|
+
"type": "omg",
|
45
|
+
"text": "lol"
|
46
|
+
}'
|
47
|
+
session.start do |dsl|
|
48
|
+
@dsl = dsl
|
49
|
+
end
|
50
|
+
|
51
|
+
expect(@dsl.bot).to receive(:event).with(JSON.parse data)
|
52
|
+
faye.send_event :message, OpenStruct.new(data: data)
|
53
|
+
end
|
54
|
+
|
55
|
+
context "bot instantiation" do
|
56
|
+
it "creates the Bot instance" do
|
57
|
+
session.start do |bot|
|
58
|
+
expect(bot).to be_a ScriptDSL
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it "intializes the Bot with the right data" do
|
63
|
+
expect(Bot).to receive(:new).with({"id" => "1234"}, session)
|
64
|
+
|
65
|
+
session.start
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Boty
|
2
|
+
module Slack
|
3
|
+
RSpec.describe Chat do
|
4
|
+
subject(:chat) { described_class.new }
|
5
|
+
|
6
|
+
let(:parameters) {
|
7
|
+
"as_user=true&channel=general"
|
8
|
+
}
|
9
|
+
|
10
|
+
let(:post_message_url) {
|
11
|
+
"https://slack.com/api/chat.postMessage?"+
|
12
|
+
"token=#{ENV['SLACK_BOT_API_TOKEN']}&#{parameters}"
|
13
|
+
}
|
14
|
+
|
15
|
+
describe "#post_message" do
|
16
|
+
it "uses api end point to send message with default parameters" do
|
17
|
+
expect(Slack::URL).to receive(:get).
|
18
|
+
with(post_message_url + "&text=omglolbbq")
|
19
|
+
chat.post_message "omglolbbq"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "uri encodes the message" do
|
23
|
+
expect(Slack::URL).to receive(:get).
|
24
|
+
with(post_message_url + "&text=omg%20lol%20bbq")
|
25
|
+
chat.post_message "omg lol bbq"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "accepts extra api parameters" do
|
29
|
+
expect(Slack::URL).to receive(:get).
|
30
|
+
with(post_message_url + "&text=omg&extra=param")
|
31
|
+
chat.post_message "omg", extra: "param"
|
32
|
+
end
|
33
|
+
|
34
|
+
context "sending to a specific channel" do
|
35
|
+
let(:parameters) { "as_user=true&channel=lol" }
|
36
|
+
|
37
|
+
it "sends to a specific channel when one is given" do
|
38
|
+
expect(Slack::URL).to receive(:get).
|
39
|
+
with(post_message_url + "&text=omg")
|
40
|
+
chat.post_message "omg", channel: "lol"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#post_im" do
|
46
|
+
let(:im_open_url) {
|
47
|
+
"https://slack.com/api/im.open?"+
|
48
|
+
"token=#{ENV['SLACK_BOT_API_TOKEN']}&user=U1234"
|
49
|
+
}
|
50
|
+
|
51
|
+
before do
|
52
|
+
allow(Slack::URL).to receive(:get).with(im_open_url).
|
53
|
+
and_return("channel" => { "id" => "C4321" })
|
54
|
+
allow(chat).to receive(:post_message)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "calls `#im.open` to open the channel" do
|
58
|
+
expect(chat.im).to receive(:open).with("U1234").
|
59
|
+
and_return Channel.new(id: "C4321", info: {})
|
60
|
+
|
61
|
+
chat.post_im "U1234", "message"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "sends the message to the im channel returned by `#im.open`" do
|
65
|
+
expect(chat).to receive(:post_message).
|
66
|
+
with "message", channel: "C4321"
|
67
|
+
|
68
|
+
chat.post_im "U1234", "message"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Boty
|
4
|
+
module Slack
|
5
|
+
RSpec.describe IM do
|
6
|
+
subject(:im) { described_class.new }
|
7
|
+
|
8
|
+
let(:action) { :open }
|
9
|
+
|
10
|
+
let(:im_url) {
|
11
|
+
"https://slack.com/api/im.#{action}?"+
|
12
|
+
"token=#{ENV['SLACK_BOT_API_TOKEN']}"
|
13
|
+
}
|
14
|
+
|
15
|
+
describe "#open" do
|
16
|
+
it "calls Slack::URL get with token and user" do
|
17
|
+
expect(Slack::URL).to receive(:get).with(im_url + "&user=U1234")
|
18
|
+
|
19
|
+
im.open "U1234"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns a channel object with the im channel information" do
|
23
|
+
expect(Slack::URL).to receive(:get).with(im_url + "&user=U1234").
|
24
|
+
and_return(
|
25
|
+
"ok" => true,
|
26
|
+
"channel" => { "id" => "D024BFF1M" }
|
27
|
+
)
|
28
|
+
|
29
|
+
expect(im.open("U1234").id).to eq "D024BFF1M"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Boty
|
2
|
+
module Slack
|
3
|
+
RSpec.describe RTM do
|
4
|
+
subject(:rtm) { described_class.new }
|
5
|
+
|
6
|
+
let(:url_with_default_parameters) {
|
7
|
+
"https://#{ENV["SLACK_COMPANY"]}.slack.com/api/rtm.start?"+
|
8
|
+
"token=#{ENV["SLACK_BOT_API_TOKEN"]}&"+
|
9
|
+
"simple_latest=true&no_unreads=true"
|
10
|
+
}
|
11
|
+
|
12
|
+
describe "#start" do
|
13
|
+
it "uses api to start the session" do
|
14
|
+
expect(Slack::URL).to receive(:get).with(url_with_default_parameters)
|
15
|
+
rtm.start
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Boty
|
2
|
+
module Slack
|
3
|
+
RSpec.describe URL do
|
4
|
+
class Pseudo
|
5
|
+
include URL
|
6
|
+
url "http://example.org"
|
7
|
+
|
8
|
+
def omg(parameters: {}, path: nil)
|
9
|
+
parameterize parameters, path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when included" do
|
14
|
+
subject(:client_class) { Pseudo }
|
15
|
+
|
16
|
+
it "injects the configuration method .url" do
|
17
|
+
expect(client_class).to respond_to :url
|
18
|
+
end
|
19
|
+
|
20
|
+
it "injects the #parameterize" do
|
21
|
+
expect(client_class.new.respond_to?(:parameterize, true)).to eq true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".get" do
|
26
|
+
subject(:url) { described_class }
|
27
|
+
|
28
|
+
it "sends the http request" do
|
29
|
+
expect(Net::HTTP).to receive(:get).with(URI("http://example.org"))
|
30
|
+
url.get "http://example.org"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "parses the json response" do
|
34
|
+
expect(Net::HTTP).to receive(:get).with(URI("http://example.org")).
|
35
|
+
and_return "{\"it\": \"works\"}"
|
36
|
+
response = url.get "http://example.org"
|
37
|
+
expect(response).to eq "it" => "works"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#parameterize" do
|
42
|
+
subject(:client) { Pseudo.new }
|
43
|
+
|
44
|
+
it "appends a path to the configured url" do
|
45
|
+
url = client.send :parameterize, {}, path: "/omg"
|
46
|
+
expect(url).to include "/omg?"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "appends the api token" do
|
50
|
+
url = client.send :parameterize, {}
|
51
|
+
expect(url).to include "token=#{ENV["SLACK_BOT_API_TOKEN"]}"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "add extra parameters" do
|
55
|
+
url = client.send :parameterize, {really: "omg"}
|
56
|
+
expect(url).to include "really=omg"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "uses the url configured by #url" do
|
60
|
+
url = client.send :parameterize, {}
|
61
|
+
expect(url).to include "http://example.org"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "applies URI.encode to parameter values" do
|
65
|
+
url = client.send :parameterize, {really: "omg lol"}
|
66
|
+
expect(url).to include "really=omg%20lol"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|