jarvis-cli 0.0.1 → 0.0.2
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 +5 -13
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/README.md +69 -5
- data/bin/jarvis +9 -0
- data/features/fact_service.feature +7 -0
- data/features/step_definitions/fact_service_steps.rb +7 -0
- data/features/step_definitions/server_steps.rb +3 -0
- data/features/support/env.rb +38 -0
- data/features/support/hooks.rb +1 -0
- data/features/support/vcr_cassettes/Fact_Service/Jarvis_responds_with_a_random_fact.yml +52 -0
- data/jarvis-cli.gemspec +8 -0
- data/lib/jarvis/cli.rb +25 -0
- data/lib/jarvis/core_ext/symbol.rb +7 -0
- data/lib/jarvis/core_ext.rb +1 -0
- data/lib/jarvis/interpreter.rb +32 -0
- data/lib/jarvis/server.rb +19 -0
- data/lib/jarvis/service.rb +73 -6
- data/lib/jarvis/services/dice.rb +25 -0
- data/lib/jarvis/services/eightball.rb +38 -0
- data/lib/jarvis/services/fact.rb +7 -0
- data/lib/jarvis/services/null_service.rb +2 -0
- data/lib/jarvis/services.rb +4 -0
- data/lib/jarvis/slack/message.rb +17 -0
- data/lib/jarvis/slack.rb +1 -0
- data/lib/jarvis/test_support/test_support.rb +20 -0
- data/lib/jarvis/version.rb +1 -1
- data/lib/jarvis.rb +19 -2
- data/spec/jarvis/interpreter_spec.rb +61 -0
- data/spec/jarvis/jarvis_spec.rb +6 -4
- data/spec/jarvis/server_spec.rb +11 -2
- data/spec/jarvis/service_spec.rb +93 -14
- data/spec/services/dice_spec.rb +22 -0
- data/spec/services/eightball_spec.rb +9 -0
- data/spec/services/fact_spec.rb +7 -0
- data/spec/services/null_service_spec.rb +3 -0
- data/spec/spec_helper.rb +53 -0
- data/spec/support/fixtures/vcr_cassettes/fact.yml +57 -0
- data/spec/support/shared_contexts/server.rb +9 -0
- data/spec/support/shared_contexts/service.rb +10 -0
- data/templates/project/Gemfile +3 -0
- data/templates/project/app/server.rb +2 -0
- data/templates/project/app/services/.gitkeep +0 -0
- data/templates/project/config.ru +4 -0
- metadata +177 -20
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Jarvis::Interpreter do
|
4
|
+
def message(params)
|
5
|
+
Slack::Message.new(slack_outgoing_message(params))
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "Defaults to NullService" do
|
9
|
+
before { Jarvis.register_services :test_service }
|
10
|
+
subject { described_class.new(message text: "success kid") }
|
11
|
+
it { expect(subject.determine_service).to eq NullService }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "Routes Services based on the registered services phrases" do
|
15
|
+
before { service.phrases = "success kid" }
|
16
|
+
before { Jarvis.register_services :test_service }
|
17
|
+
context "A Match" do
|
18
|
+
subject { described_class.new(message text: "success kid") }
|
19
|
+
it { expect(subject.determine_service).to eq service }
|
20
|
+
end
|
21
|
+
context "No Match" do
|
22
|
+
subject { described_class.new(message text: "blah") }
|
23
|
+
it { expect(subject.determine_service).to eq NullService }
|
24
|
+
end
|
25
|
+
context "Generated regex is case insensitive" do
|
26
|
+
subject { described_class.new(message text: "SUCCESS KID") }
|
27
|
+
it { expect(subject.determine_service).to eq service}
|
28
|
+
end
|
29
|
+
context "Multiple phrases route correctly" do
|
30
|
+
before(:each) { other_service.phrases = "overly attached bot", "hello world" }
|
31
|
+
before { Jarvis.register_services :other_test_service }
|
32
|
+
it { expect(described_class.new(message text: "hello world").determine_service).to eq other_service }
|
33
|
+
it { expect(described_class.new(message text: "overly attached bot").determine_service).to eq other_service }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "Routes services based on the registered interpreter pattern" do
|
38
|
+
before { service.interpreter_pattern = /success kid/i }
|
39
|
+
before { Jarvis.register_services :test_service }
|
40
|
+
context "A Match" do
|
41
|
+
subject { described_class.new(message text: "success kid") }
|
42
|
+
it { expect(subject.determine_service).to eq service }
|
43
|
+
end
|
44
|
+
context "No Match" do
|
45
|
+
subject { described_class.new(message text: "blah") }
|
46
|
+
it { expect(subject.determine_service).to eq NullService }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "Routes to the correct service" do
|
51
|
+
let(:correct_service) { service }
|
52
|
+
let(:incorrect_service) { other_service }
|
53
|
+
before { correct_service.interpreter_pattern = /success kid/i }
|
54
|
+
before { incorrect_service.interpreter_pattern = /overly attached chatbot/i }
|
55
|
+
before { Jarvis.register_services :test_service, :other_test_service }
|
56
|
+
context "Routes to Test Service" do
|
57
|
+
subject { described_class.new(message text: "success kid hello, world") }
|
58
|
+
it { expect(subject.determine_service).to eq correct_service }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/spec/jarvis/jarvis_spec.rb
CHANGED
@@ -4,10 +4,12 @@ RSpec.describe Jarvis do
|
|
4
4
|
|
5
5
|
describe "Service Registry" do
|
6
6
|
it "Allows you to register a Jarvis::Service subclass" do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
Jarvis.register_services(:test_service)
|
8
|
+
expect(Jarvis.services).to eq [:test_service]
|
9
|
+
end
|
10
|
+
it "Works with multiple classes" do
|
11
|
+
Jarvis.register_services :test_service, :other_test_service
|
12
|
+
expect(Jarvis.services).to eq [:test_service, :other_test_service]
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
data/spec/jarvis/server_spec.rb
CHANGED
@@ -2,10 +2,19 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
RSpec.describe Jarvis::Server do
|
4
4
|
let(:parsed_response) { JSON.parse(last_response.body) }
|
5
|
-
|
5
|
+
let(:message) { parsed_response["text"] }
|
6
6
|
describe "get /" do
|
7
7
|
before { get "/" }
|
8
8
|
it { expect(last_response).to be_ok }
|
9
|
-
it { expect(
|
9
|
+
it { expect(message).to eq "Hello, I'm Jarvis" }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "unfit environment" do
|
13
|
+
let(:slack_message) { slack_outgoing_message(text: "Jarvis, success kid blah blah blah") }
|
14
|
+
before { service.environment :blah }
|
15
|
+
before { service.phrases = "success kid" }
|
16
|
+
before { Jarvis.register_services :test_service }
|
17
|
+
before { post "/jarvis", slack_message }
|
18
|
+
it { expect(message).to eq "I'm really sorry, but that sevice needs to be configured" }
|
10
19
|
end
|
11
20
|
end
|
data/spec/jarvis/service_spec.rb
CHANGED
@@ -1,33 +1,112 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
RSpec.describe Jarvis::Service do
|
4
|
-
|
4
|
+
let(:message) { double("Slack::Message") }
|
5
5
|
describe "Validate Environment Variables are Present" do
|
6
|
-
|
7
|
-
|
8
|
-
required_environment "SERVICE_TOKEN"
|
9
|
-
end
|
10
|
-
|
11
|
-
subject { MyService.new }
|
12
|
-
|
6
|
+
before { service.environment :service_token }
|
7
|
+
subject { service.new message }
|
13
8
|
context "Required Environment not set up" do
|
14
9
|
it { expect { subject.validate_environment }.to raise_exception(Jarvis::UnfitEnvironmentException) }
|
15
10
|
end
|
16
11
|
|
17
12
|
context "Environment Correctly Set Up" do
|
18
|
-
before {
|
13
|
+
before { stub_env("SERVICE_TOKEN" => "token") }
|
14
|
+
it { expect { subject.validate_environment }.to_not raise_exception }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "tries lowercase environment variable if uppercase isn't present" do
|
18
|
+
before { service.environment :service_token }
|
19
|
+
before { stub_env("SERVICE_TOKEN" => nil, "service_token" => "token")}
|
20
|
+
subject { service.new message }
|
19
21
|
it { expect { subject.validate_environment }.to_not raise_exception }
|
20
22
|
end
|
21
23
|
|
22
24
|
context "Multiple Required Variables, Some not present" do
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
subject { MyOtherService.new }
|
27
|
-
before { ENV["SERVICE_TOKEN"] = "token" }
|
25
|
+
before { service.environment :service_token, :service_secret }
|
26
|
+
before { stub_env("SERVICE_TOKEN" => "token", "SERVICE_SECRET" => nil, "service_secret" => nil) }
|
28
27
|
it { expect { subject.validate_environment }.to raise_exception(Jarvis::UnfitEnvironmentException) }
|
29
28
|
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "Expose Pattern For the Service to be Interpreted" do
|
32
|
+
before { service.interpreter_pattern = /are you up/i }
|
33
|
+
it { expect(service.interpreter_pattern).to eq /are you up/i }
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "Allow the Developer to make a list of phrases to be concatenated into the interpreter pattern" do
|
37
|
+
context "Accepts a single phrase" do
|
38
|
+
before { service.phrases = "success kid" }
|
39
|
+
it { expect(service.interpreter_pattern ).to eq /success kid/i }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "Multiple Phrases" do
|
43
|
+
before { service.phrases = "success kid", "hello world" }
|
44
|
+
it { expect(service.interpreter_pattern).to eq /success kid|hello world/i }
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "Environment Accessor" do
|
50
|
+
context "Uppercase" do
|
51
|
+
before { service.environment :service_token }
|
52
|
+
before { stub_env("SERVICE_TOKEN" => "token") }
|
53
|
+
subject { service.new message }
|
54
|
+
it { expect(subject.service_token).to eq "token"}
|
55
|
+
end
|
56
|
+
context "Lowercase" do
|
57
|
+
before { service.environment :service_token }
|
58
|
+
before { stub_env("SERVICE_TOKEN" => nil, "service_token" => "token") }
|
59
|
+
subject { service.new message }
|
60
|
+
it { expect(subject.service_token).to eq "token"}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "invoke_with" do
|
65
|
+
describe "defaults to run" do
|
66
|
+
before do
|
67
|
+
class TestService < Jarvis::Service
|
68
|
+
def run
|
69
|
+
"Hello World"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
it { expect(service.new(message).invoke).to eq "Hello World" }
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "Can be overridden with #invoke_with" do
|
77
|
+
before do
|
78
|
+
class OtherTestService < Jarvis::Service
|
79
|
+
invoke_with :call_me_maybe
|
80
|
+
def call_me_maybe
|
81
|
+
"This is crazy"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
it { expect(other_service.new(message).invoke).to eq "This is crazy" }
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "before_invoke" do
|
91
|
+
before { class TestService < Jarvis::Service
|
92
|
+
before_invoke :puts_hello
|
93
|
+
def puts_hello
|
94
|
+
puts "Hello"
|
95
|
+
end
|
96
|
+
end }
|
97
|
+
|
98
|
+
it { expect { service.new(message).invoke }.to output("Hello\n").to_stdout }
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "after_invoke" do
|
102
|
+
before { class TestService < Jarvis::Service
|
103
|
+
after_invoke :puts_hello
|
104
|
+
def puts_hello
|
105
|
+
puts "Hello"
|
106
|
+
end
|
107
|
+
end }
|
30
108
|
|
109
|
+
it { expect { service.new(message).invoke }.to output("Hello\n").to_stdout }
|
31
110
|
end
|
32
111
|
|
33
112
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Dice do
|
4
|
+
context "d6" do
|
5
|
+
let(:message) { Slack::Message.new slack_outgoing_message(text: "Jarvis, roll 1d6") }
|
6
|
+
subject { described_class.new(message) }
|
7
|
+
before { allow(subject).to receive(:roll) { 5 }}
|
8
|
+
it { expect(subject.invoke).to eq "You got a 5" }
|
9
|
+
end
|
10
|
+
context "2d6" do
|
11
|
+
let(:message) { Slack::Message.new slack_outgoing_message(text: "Jarvis, roll 2d6") }
|
12
|
+
subject { described_class.new(message) }
|
13
|
+
before { allow(subject).to receive(:roll).and_return(1, 6) }
|
14
|
+
it { expect(subject.invoke).to eq "You got a 7" }
|
15
|
+
end
|
16
|
+
context "5d20" do
|
17
|
+
let(:message) { Slack::Message.new slack_outgoing_message(text: "Jarvis, roll 5d20") }
|
18
|
+
subject { described_class.new(message) }
|
19
|
+
before { allow(subject).to receive(:roll).and_return(1, 12, 20, 3, 4) }
|
20
|
+
it { expect(subject.invoke).to eq "You got a 40" }
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Eightball do
|
4
|
+
|
5
|
+
let(:message) { Slack::Message.new slack_outgoing_message(text: "Jarvis, will I ship this gem today?")}
|
6
|
+
subject { described_class.new(message) }
|
7
|
+
before { allow_any_instance_of(Array).to receive(:sample) { "Outlook not so good" } }
|
8
|
+
specify { expect(subject.invoke).to eq "Outlook not so good" }
|
9
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Fact, vcr: { cassette_name: 'fact' } do
|
4
|
+
let(:message) { Slack::Message.new(slack_outgoing_message(text: "Jarvis, fact")) }
|
5
|
+
subject { described_class.new message }
|
6
|
+
it { expect(subject.invoke).to eq "182 is the carat of the Star of Bombay cabochon-cut star sapphire originating from Sri Lanka." }
|
7
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,6 +3,10 @@ require 'rspec'
|
|
3
3
|
require 'rack/test'
|
4
4
|
require 'json'
|
5
5
|
require 'jarvis'
|
6
|
+
require 'byebug'
|
7
|
+
require 'vcr'
|
8
|
+
require_relative './support/shared_contexts/service'
|
9
|
+
require_relative './support/shared_contexts/server'
|
6
10
|
|
7
11
|
include Rack::Test::Methods
|
8
12
|
|
@@ -10,6 +14,55 @@ def app
|
|
10
14
|
Jarvis::Server
|
11
15
|
end
|
12
16
|
|
17
|
+
def stub_env(hash)
|
18
|
+
hash.each do |key, value|
|
19
|
+
allow(ENV).to receive(:[]).with(key) { value }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def slack_outgoing_message(options={text:"Jarvis, what's going on?"})
|
24
|
+
{
|
25
|
+
"team_id" => options[:team_id] || "T0001",
|
26
|
+
"channel_id" => options[:channel_id] || "BLAH",
|
27
|
+
"channel_name" => options[:channel_name] || "test",
|
28
|
+
"timestamp" => options[:timestamp] || "1355517523.000005",
|
29
|
+
"user_id" => options[:user_id] || "U2147483697",
|
30
|
+
"user_name" => options[:user_name] || "Steve",
|
31
|
+
"text" => options[:text],
|
32
|
+
"trigger_word" => options[:trigger_word] || "Jarvis"
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
13
36
|
RSpec.configure do |config|
|
14
37
|
config.expose_dsl_globally = false
|
38
|
+
config.around(:each) do |example|
|
39
|
+
class TestService < Jarvis::Service
|
40
|
+
def run
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
class OtherTestService < Jarvis::Service
|
45
|
+
def run
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
class TestServer < Jarvis::Server
|
50
|
+
end
|
51
|
+
|
52
|
+
example.run
|
53
|
+
|
54
|
+
Jarvis.clear_services
|
55
|
+
|
56
|
+
Object.send :remove_const, :TestServer
|
57
|
+
Object.send :remove_const, :TestService
|
58
|
+
Object.send :remove_const, :OtherTestService
|
59
|
+
end
|
60
|
+
config.include ServerContext
|
61
|
+
config.include ServiceContext
|
62
|
+
end
|
63
|
+
|
64
|
+
VCR.configure do |config|
|
65
|
+
config.cassette_library_dir = "spec/support/fixtures/vcr_cassettes"
|
66
|
+
config.configure_rspec_metadata!
|
67
|
+
config.hook_into :webmock
|
15
68
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://numbersapi.com/random
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- nginx/1.4.6 (Ubuntu)
|
23
|
+
Date:
|
24
|
+
- Fri, 20 Feb 2015 05:01:41 GMT
|
25
|
+
Content-Type:
|
26
|
+
- text/plain; charset="UTF-8"; charset=utf-8
|
27
|
+
Content-Length:
|
28
|
+
- '93'
|
29
|
+
X-Powered-By:
|
30
|
+
- Express
|
31
|
+
Access-Control-Allow-Origin:
|
32
|
+
- "*"
|
33
|
+
Access-Control-Allow-Headers:
|
34
|
+
- X-Requested-With
|
35
|
+
X-Numbers-Api-Number:
|
36
|
+
- '182'
|
37
|
+
X-Numbers-Api-Type:
|
38
|
+
- trivia
|
39
|
+
Pragma:
|
40
|
+
- no-cache
|
41
|
+
Cache-Control:
|
42
|
+
- no-cache
|
43
|
+
Expires:
|
44
|
+
- '0'
|
45
|
+
Proxy-Connection:
|
46
|
+
- Keep-Alive
|
47
|
+
Connection:
|
48
|
+
- Keep-Alive
|
49
|
+
Age:
|
50
|
+
- '0'
|
51
|
+
body:
|
52
|
+
encoding: UTF-8
|
53
|
+
string: 182 is the carat of the Star of Bombay cabochon-cut star sapphire originating
|
54
|
+
from Sri Lanka.
|
55
|
+
http_version:
|
56
|
+
recorded_at: Fri, 20 Feb 2015 05:01:27 GMT
|
57
|
+
recorded_with: VCR 2.9.3
|
File without changes
|