watsbot 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.byebug_history +71 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.simplecov +4 -0
- data/.travis.yml +14 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Guardfile +26 -0
- data/LICENSE.txt +21 -0
- data/README.md +63 -0
- data/Rakefile +11 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/watsbot.rb +33 -0
- data/lib/watsbot/base_resource.rb +19 -0
- data/lib/watsbot/configuration.rb +16 -0
- data/lib/watsbot/logger.rb +50 -0
- data/lib/watsbot/message.rb +47 -0
- data/lib/watsbot/response/error.rb +5 -0
- data/lib/watsbot/response/parser.rb +38 -0
- data/lib/watsbot/response/success.rb +5 -0
- data/lib/watsbot/state.rb +29 -0
- data/lib/watsbot/version.rb +3 -0
- data/spec/configuration_spec.rb +149 -0
- data/spec/fixtures/message/created.txt +21 -0
- data/spec/fixtures/message/error.txt +21 -0
- data/spec/helpers.rb +20 -0
- data/spec/message_spec.rb +65 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/state_spec.rb +67 -0
- data/spec/version_spec.rb +12 -0
- data/watsbot.gemspec +41 -0
- metadata +296 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
require "httparty"
|
2
|
+
require "celluloid"
|
3
|
+
|
4
|
+
module Watsbot
|
5
|
+
class Message < BaseResource
|
6
|
+
include HTTParty
|
7
|
+
|
8
|
+
def send(uid, message, context={})
|
9
|
+
raise "uid should be provided" and return if uid.nil? or uid.empty?
|
10
|
+
raise "message should be provided" and return if message.nil? or message.empty?
|
11
|
+
|
12
|
+
future = Celluloid::Future.new { call(uid, message, context={}) }
|
13
|
+
future.value
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def call(uid, message, context={})
|
19
|
+
state = State.instance
|
20
|
+
context = JSON.parse(state.fetch(uid)) rescue nil
|
21
|
+
response = call_api(message, context)
|
22
|
+
change_state(state, uid, response)
|
23
|
+
response
|
24
|
+
end
|
25
|
+
|
26
|
+
def change_state(state, uid, response)
|
27
|
+
if response.is_a? Response::Success
|
28
|
+
if response.context["system"]["branch_exited_reason"] == 'completed'
|
29
|
+
state.delete(uid)
|
30
|
+
elsif response.context["system"]["branch_exited_reason"] != 'fallback'
|
31
|
+
state.store(uid, response.context.to_json)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
state.delete(uid)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def call_api(message, context={})
|
39
|
+
body = { input: { text: message }, context: context }
|
40
|
+
options = { basic_auth: basic_auth, headers: headers, body: body.to_json }
|
41
|
+
response = self.class.post("/workspaces/#{Watsbot.configuration.workspace}/message?version=#{Watsbot.configuration.version}", options)
|
42
|
+
logger.info("/log/watsbot.log", "watson api _> #{options.inspect} -- #{response}")
|
43
|
+
parser = Watsbot::Response::Parser.new response
|
44
|
+
parser.parse
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Watsbot
|
2
|
+
module Response
|
3
|
+
class Parser
|
4
|
+
|
5
|
+
def initialize(response)
|
6
|
+
@response = response
|
7
|
+
@response_body = JSON.parse(response.body)
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse
|
11
|
+
if @response.code >= 400
|
12
|
+
response = Error.new @response.code
|
13
|
+
response.message = parse_error_message
|
14
|
+
response
|
15
|
+
else
|
16
|
+
response = Success.new @response.code
|
17
|
+
response.intents = @response_body["intents"]
|
18
|
+
response.entities = parse_entities
|
19
|
+
response.input = @response_body["input"]
|
20
|
+
response.output = @response_body["output"]
|
21
|
+
response.context = @response_body["context"]
|
22
|
+
response
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def parse_error_message
|
29
|
+
@response_body["error"]["error"] rescue ""
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_entities
|
33
|
+
@response_body["entities"]
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "redis"
|
2
|
+
require "singleton"
|
3
|
+
|
4
|
+
module Watsbot
|
5
|
+
class State
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@redis = Redis.new(:url => Watsbot.configuration.redis_url)
|
10
|
+
end
|
11
|
+
|
12
|
+
def fetch(key)
|
13
|
+
@redis.get(key)
|
14
|
+
end
|
15
|
+
|
16
|
+
def store(key, value)
|
17
|
+
@redis.set(key, value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def exists?(key)
|
21
|
+
@redis.exists(key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete(key)
|
25
|
+
@redis.del(key)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Watsbot
|
4
|
+
RSpec.describe Configuration do
|
5
|
+
|
6
|
+
after :each do
|
7
|
+
Watsbot.reset
|
8
|
+
end
|
9
|
+
|
10
|
+
context "username" do
|
11
|
+
it "should return default username from environment variable" do
|
12
|
+
allow(ENV).to receive(:[]).and_return(nil)
|
13
|
+
allow(ENV).to receive(:[]).with("WATSON_USERNAME").and_return("test")
|
14
|
+
Configuration.new.username
|
15
|
+
expect(Configuration.new.username).to eq("test")
|
16
|
+
end
|
17
|
+
it "should set username" do
|
18
|
+
config = Configuration.new
|
19
|
+
config.username = "test"
|
20
|
+
expect(config.username).to eq("test")
|
21
|
+
end
|
22
|
+
it "should set username with argument" do
|
23
|
+
config = Configuration.new username: "test"
|
24
|
+
expect(config.username).to eq("test")
|
25
|
+
end
|
26
|
+
it "should set username with block" do
|
27
|
+
config = Configuration.new do |c|
|
28
|
+
c.username = "username"
|
29
|
+
end
|
30
|
+
expect(config.username).to eq("username")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "password" do
|
35
|
+
it "should return default password from environment variable" do
|
36
|
+
allow(ENV).to receive(:[]).and_return(nil)
|
37
|
+
allow(ENV).to receive(:[]).with("WATSON_PASSWORD").and_return("test")
|
38
|
+
Configuration.new.password
|
39
|
+
expect(Configuration.new.password).to eq("test")
|
40
|
+
end
|
41
|
+
it "should set password" do
|
42
|
+
config = Configuration.new
|
43
|
+
config.password = "test"
|
44
|
+
expect(config.password).to eq("test")
|
45
|
+
end
|
46
|
+
it "should set password with argument" do
|
47
|
+
config = Configuration.new password: "test"
|
48
|
+
expect(config.password).to eq("test")
|
49
|
+
end
|
50
|
+
it "should set password with block" do
|
51
|
+
config = Configuration.new do |c|
|
52
|
+
c.password = "password"
|
53
|
+
end
|
54
|
+
expect(config.password).to eq("password")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "workspace" do
|
59
|
+
it "should return default workspace from environment variable" do
|
60
|
+
allow(ENV).to receive(:[]).and_return(nil)
|
61
|
+
allow(ENV).to receive(:[]).with("WATSON_WORKSPACE").and_return("test")
|
62
|
+
Configuration.new.workspace
|
63
|
+
expect(Configuration.new.workspace).to eq("test")
|
64
|
+
end
|
65
|
+
it "should set workspace" do
|
66
|
+
config = Configuration.new
|
67
|
+
config.workspace = "test"
|
68
|
+
expect(config.workspace).to eq("test")
|
69
|
+
end
|
70
|
+
it "should set workspace with argument" do
|
71
|
+
config = Configuration.new workspace: "test"
|
72
|
+
expect(config.workspace).to eq("test")
|
73
|
+
end
|
74
|
+
it "should set workspace with block" do
|
75
|
+
config = Configuration.new do |c|
|
76
|
+
c.workspace = "workspace"
|
77
|
+
end
|
78
|
+
expect(config.workspace).to eq("workspace")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "version" do
|
83
|
+
it "should return default version from environment variable" do
|
84
|
+
allow(ENV).to receive(:[]).and_return(nil)
|
85
|
+
allow(ENV).to receive(:[]).with("WATSON_WORKSPACE_VERSION").and_return("test")
|
86
|
+
Configuration.new.version
|
87
|
+
expect(Configuration.new.version).to eq("test")
|
88
|
+
end
|
89
|
+
it "should set version" do
|
90
|
+
config = Configuration.new
|
91
|
+
config.version = "test"
|
92
|
+
expect(config.version).to eq("test")
|
93
|
+
end
|
94
|
+
it "should set version with argument" do
|
95
|
+
config = Configuration.new version: "test"
|
96
|
+
expect(config.version).to eq("test")
|
97
|
+
end
|
98
|
+
it "should set version with block" do
|
99
|
+
config = Configuration.new do |c|
|
100
|
+
c.version = "version"
|
101
|
+
end
|
102
|
+
expect(config.version).to eq("version")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "redis_url" do
|
107
|
+
it "should return default redis_url from environment variable" do
|
108
|
+
allow(ENV).to receive(:[]).and_return(nil)
|
109
|
+
allow(ENV).to receive(:[]).with("REDIS_URL").and_return("test")
|
110
|
+
Configuration.new.redis_url
|
111
|
+
expect(Configuration.new.redis_url).to eq("test")
|
112
|
+
end
|
113
|
+
it "should set redis_url" do
|
114
|
+
config = Configuration.new
|
115
|
+
config.redis_url = "test"
|
116
|
+
expect(config.redis_url).to eq("test")
|
117
|
+
end
|
118
|
+
it "should set redis_url with argument" do
|
119
|
+
config = Configuration.new redis_url: "test"
|
120
|
+
expect(config.redis_url).to eq("test")
|
121
|
+
end
|
122
|
+
it "should set redis_url with block" do
|
123
|
+
config = Configuration.new do |c|
|
124
|
+
c.redis_url = "redis_url"
|
125
|
+
end
|
126
|
+
expect(config.redis_url).to eq("redis_url")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "base uri" do
|
131
|
+
it "should return default base uri" do
|
132
|
+
expect(Configuration.new.base_uri.nil?).to be false
|
133
|
+
expect(Configuration.new.base_uri.length).to be > 0
|
134
|
+
end
|
135
|
+
it "should set base uri" do
|
136
|
+
config = Configuration.new
|
137
|
+
config.base_uri = "http://mycustom.url"
|
138
|
+
expect(config.base_uri).to eq("http://mycustom.url")
|
139
|
+
end
|
140
|
+
it "should set base uri with block" do
|
141
|
+
config = Configuration.new do |c|
|
142
|
+
c.base_uri = "http://mycustomapi.url"
|
143
|
+
end
|
144
|
+
expect(config.base_uri).to eq("http://mycustomapi.url")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
X-Backside-Transport: OK OK
|
3
|
+
Connection: Keep-Alive
|
4
|
+
Transfer-Encoding: chunked
|
5
|
+
X-Frame-Options: SAMEORIGIN
|
6
|
+
Strict-Transport-Security: max-age=31536000;
|
7
|
+
ETag: W/"1cd-XPBepDE7HNqNr6wZapZ1+w"
|
8
|
+
X-Content-Type-Options: nosniff
|
9
|
+
X-Download-Options: noopen
|
10
|
+
X-DNS-Prefetch-Control: off
|
11
|
+
Vary: Accept-Encoding
|
12
|
+
X-XSS-Protection: 1; mode=block
|
13
|
+
Date: Tue, 23 May 2017 10:26:14 GMT
|
14
|
+
Content-Type: application/json;charset=utf-8
|
15
|
+
Server: -
|
16
|
+
Set-Cookie: Watson-DPAT=1IUyfHxFvm9UhVYgNXBRScD8lDxY2xWsK3xSpNYmKq5YY0exS%2Fqtz55Sxg9Ys6%2F7v18ofQ9%2BhmrP68PBAMHjkJ4jGENioEoqtqWnU4ts4s0D9%2FTj9dniC7UxKdUsw9eUF32Usd4UVuvSb%2BWSEETs2HoL4GTHZxxWa0jeUXgI2CDSsvPpiSypRfvQz8Jqb9naK1TA2qyWOlNxLRvmFlmhdlBGrIXsp9QhgPeEgikZK9d4MZrdZXw6ht2T%2FJo93BsGgzrUf0ForfXw2pjh6MuAIFNTFzzeTkhqTyCF1GOxFmbDCObOgLTO2tuWTpn7pAiLNUL2vsogOWlf0GEsZSh012hpxPsNj0OCigne%2FxyY5Dj9o%2FY0HXvSa17A71qlIrFoYs0kyC5YCuiWOOOMfP56Jf6Ztnu39SVEKGxHRlSiT2udAJMS4t5jm0kF%2BkP%2BhBOHSOgMJGil5x25ArJtM0YfrunF81mskUM77aYUtHE%2BosCYFIgylZ3mH%2BC6mo3eG2qe76Gj1Uu5LQSSPX1Hm5mcnEsiSISyHfSveIKlb7OaYM9kjRHHsbLjnHfy2CZv7nSBKIFQMCiQk4FrRv3meSqCGz%2BmFeKCo04Cs75%2F6ySShVDA1yhJW8LhPaHhnRtXwm0zbFT4hD4qBTbFmW%2FxXdPJcsE%2B40ltYh%2FQ5H6yIAAYykujtkHCigkTrjiIiyPmAgB9zSx7sl934Lf1XVeSsDNJS83jyqOCG804BCZN8bfhRY4%2BxvjR5zD9Rm%2Fy6Rl9n%2BNOIV9F7aV45YTvHRJ%2FEHPDb5AIl9dwqsW0nfaz43KeZ7K9F2cqgHOP7fJCmUE9Q2e%2FkoUikETdW5q5JxuxntQ6BALK%2BtfC%2FbLIJORiDKm4%2FhKtKlBPoRsdANOkpdAe7%2FjugaJWkmPQ7ayYTOfBlHCyZoYUtbSL9AJFFgaq9utrNqe5Fr0VGnQ4TV%2Fn%2BmxcXYlQSTcDGS%2F8mpm0FLDXtqxuIg%3D%3D; path=/conversation/api; secure; HttpOnly
|
17
|
+
X-Client-IP: 220.101.98.130
|
18
|
+
X-Global-Transaction-ID: 1468324772
|
19
|
+
X-DP-Watson-Tran-ID: gateway-dp02-1468324772
|
20
|
+
|
21
|
+
{"intents":[{"intent":"Greeting","confidence":1}],"entities":[{"entity":"Greeting","location":[0,2],"value":"Hi","confidence":1}],"input":{"text":"hi"},"output":{"log_messages":[],"text":["Hi, how are you?"],"nodes_visited":["greeting"]},"context":{"conversation_id":"d17270f6-671e-473b-b981-65761a9d5128","system":{"dialog_stack":[{"dialog_node":"greeting"}],"dialog_turn_counter":1,"dialog_request_counter":1,"_node_output_map":{"node_2_1494386292425":[0]}}}}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
HTTP/1.1 400 Bad Request
|
2
|
+
X-Backside-Transport: FAIL FAIL
|
3
|
+
Connection: Keep-Alive
|
4
|
+
Transfer-Encoding: chunked
|
5
|
+
X-Frame-Options: SAMEORIGIN
|
6
|
+
Strict-Transport-Security: max-age=31536000;
|
7
|
+
ETag: W/"37-GiTifP4vb9PqzZCy57Cz7A"
|
8
|
+
X-Content-Type-Options: nosniff
|
9
|
+
X-Download-Options: noopen
|
10
|
+
X-DNS-Prefetch-Control: off
|
11
|
+
Vary: Accept-Encoding
|
12
|
+
X-XSS-Protection: 1; mode=block
|
13
|
+
Date: Tue, 23 May 2017 10:59:42 GMT
|
14
|
+
Content-Type: application/json;charset=utf-8
|
15
|
+
Server: -
|
16
|
+
Set-Cookie: Watson-DPAT=AqqzbJRf25aUFnKhzKDjg%2Bmqhdx%2BKMTTg8I9RMzub6jsDkn6kC2ObdYFLwjUBhXglnrH47KPEBaC7dF5G62Gsh9kklkjKX4GLW5j%2BztLAh3dr4tv6jt9qN97W4URreaF99zP0fLHH%2FDvyYxTAw0VSvGpNc5%2B0kC%2FOukrM7EUDXdsgN%2FQdglfeTficysYFhaq%2FXLs6rphgcD5m7x99klh1Bh4aFjaSueecLB%2FEV8WUhb281%2FZIRFKgVE%2F2IB3V8PV3D1oXtTIjJHeumVRc7JGIHcXy%2Ba0DI%2BFAr8zI0mSKz7LqB%2Fq8OWikXssLZW3Noojlq9FX1hNYIMxOup583aeptDJhpSe%2BIV2rCrqAYafVy8s2%2BcLovB3WdHPFmE35cAmm%2BokC1PU4CMXoslsDk5sN97CfwVXaFJdKg1cviKFcw6hwX0aHTauNof8kbXC2aGStG%2F0e8nkXFs2bFAhANJ8u88x57i5ciS8fnry5ZwZZiFxs4qTbOKADuoV3r96ClrwAtodeLdMYJCClMFENb4IMqnMmhgOo8sjHCoDqJH8LHJEVCxxSlgJrb4wcCtVAEJDeVxejl2v5dokRakBWvdG%2BwOvVcgR41LzQ6n8Xj%2BtQ2HfUsfzaHT33KsoXHYFHTcC8elzq5R0z8G6WrGZMAaAtxwwsaGGaKbVKyruGRP0AyYI2QwW9%2FWYUzzXHoTt6r9cQBbru72gyIVDQwGanMSLt6h3QDwXDsTb4I5JVB0E9T3sR1fUt1SEivUBZqipCvgctp%2BbVAKbnZNr4OjDOxL0VbS2WiCvr6p3RGi39KXfH500xUpWJXtcPNi8xLtNjKEVnoancJYZmC20p6WYqnEJAHva4BgkxrDZOsAsxS4XvVSzcyYtxOnBceCsOvMVtt2xYhF68OrShMp9VAJkd75qYoJTHGJQ5BW%2FysMY4djh5xdrtsI4EvvwzvHHLQezcOp2P0d57h%2BqhUY%3D; path=/conversation/api; secure; HttpOnly
|
17
|
+
X-Client-IP: 220.101.98.130
|
18
|
+
X-Global-Transaction-ID: 1437918292
|
19
|
+
X-DP-Watson-Tran-ID: gateway-dp01-1437918292
|
20
|
+
|
21
|
+
{"error":{"error":"Missing 'version' query parameter"}}
|
data/spec/helpers.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
def spec_dir
|
3
|
+
File.join Watsbot.root, "spec"
|
4
|
+
end
|
5
|
+
|
6
|
+
def fixture_dir
|
7
|
+
File.join spec_dir, "fixtures"
|
8
|
+
end
|
9
|
+
|
10
|
+
def watson_uri(path)
|
11
|
+
Watsbot::BASE_URI + path
|
12
|
+
end
|
13
|
+
|
14
|
+
def watson_ruri(path)
|
15
|
+
%r{#{watson_uri(path)}}
|
16
|
+
end
|
17
|
+
|
18
|
+
def fixture_path(file)
|
19
|
+
File.new File.join(fixture_dir, file)
|
20
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Watsbot
|
4
|
+
RSpec.describe Message do
|
5
|
+
|
6
|
+
let(:valid_config) {
|
7
|
+
Watsbot::Configuration.new(
|
8
|
+
username: ENV["WATSON_USERNAME"],
|
9
|
+
password: ENV["WATSON_PASSWORD"],
|
10
|
+
workspace: ENV["WATSON_WORKSPACE"],
|
11
|
+
version: ENV["WATSON_WORKSPACE_VERSION"],
|
12
|
+
redis_url: ENV["REDIS_URL"]
|
13
|
+
)
|
14
|
+
}
|
15
|
+
|
16
|
+
describe "#send" do
|
17
|
+
context "invalid" do
|
18
|
+
it "raises error - no uid" do
|
19
|
+
message = Watsbot::Message.new(valid_config)
|
20
|
+
expect { message.send(nil, "Hi", {}) }.to raise_error("uid should be provided")
|
21
|
+
end
|
22
|
+
it "raises error - no message" do
|
23
|
+
message = Watsbot::Message.new(valid_config)
|
24
|
+
uid = SecureRandom.uuid
|
25
|
+
expect { message.send(uid, nil, {}) }.to raise_error("message should be provided")
|
26
|
+
end
|
27
|
+
it "raises error - blank uid" do
|
28
|
+
message = Watsbot::Message.new(valid_config)
|
29
|
+
expect { message.send('', "Hi", {}) }.to raise_error("uid should be provided")
|
30
|
+
end
|
31
|
+
it "raises error - blank message" do
|
32
|
+
message = Watsbot::Message.new(valid_config)
|
33
|
+
uid = SecureRandom.uuid
|
34
|
+
expect { message.send(uid, '', {}) }.to raise_error("message should be provided")
|
35
|
+
end
|
36
|
+
it "responds with error state - no version" do
|
37
|
+
stub_request(:post, watson_uri("/workspaces/#{Watsbot.configuration.workspace}/message?version=")).to_return(fixture_path("message/error.txt"))
|
38
|
+
message = Watsbot::Message.new(valid_config)
|
39
|
+
uid = SecureRandom.uuid
|
40
|
+
Watsbot.configuration.version = nil
|
41
|
+
response = message.send(uid, "Hi", {})
|
42
|
+
expect(response.class).to eq(Response::Error)
|
43
|
+
Watsbot.configuration.version = ENV['WATSON_WORKSPACE_VERSION']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
context "valid" do
|
47
|
+
it "responds with success state" do
|
48
|
+
stub_request(:post, watson_uri("/workspaces/#{Watsbot.configuration.workspace}/message?version=#{Watsbot.configuration.version}")).to_return(fixture_path("message/created.txt"))
|
49
|
+
message = Watsbot::Message.new(valid_config)
|
50
|
+
uid = SecureRandom.uuid
|
51
|
+
response = message.send(uid, "Hi", {})
|
52
|
+
expect(response.class).to eq(Response::Success)
|
53
|
+
end
|
54
|
+
it "stores the context" do
|
55
|
+
stub_request(:post, watson_uri("/workspaces/#{Watsbot.configuration.workspace}/message?version=#{Watsbot.configuration.version}")).to_return(fixture_path("message/created.txt"))
|
56
|
+
message = Watsbot::Message.new(valid_config)
|
57
|
+
uid = SecureRandom.uuid
|
58
|
+
message.send(uid, "Hi", {})
|
59
|
+
expect(State.instance.fetch(uid)).not_to eq(nil)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "watsbot"
|
3
|
+
require "pry"
|
4
|
+
require "simplecov"
|
5
|
+
require "webmock/rspec"
|
6
|
+
require "byebug"
|
7
|
+
require "helpers"
|
8
|
+
require "securerandom"
|
9
|
+
require "dotenv"
|
10
|
+
|
11
|
+
Dotenv.load
|
12
|
+
WebMock.enable!
|
13
|
+
SimpleCov.start
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
17
|
+
config.disable_monkey_patching!
|
18
|
+
config.expect_with :rspec do |c|
|
19
|
+
c.syntax = :expect
|
20
|
+
end
|
21
|
+
end
|
data/spec/state_spec.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Watsbot
|
4
|
+
RSpec.describe State do
|
5
|
+
|
6
|
+
describe "#fetch" do
|
7
|
+
it "returns nil" do
|
8
|
+
state = State.instance
|
9
|
+
uid = SecureRandom.uuid
|
10
|
+
expect(state.fetch(uid)).to be(nil)
|
11
|
+
end
|
12
|
+
it "returns data" do
|
13
|
+
state = State.instance
|
14
|
+
uid = SecureRandom.uuid
|
15
|
+
data = { data: {} }
|
16
|
+
state.store(uid, data.to_json)
|
17
|
+
expect(state.fetch(uid)).to eq(data.to_json)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#store" do
|
22
|
+
it "returns data" do
|
23
|
+
state = State.instance
|
24
|
+
uid = SecureRandom.uuid
|
25
|
+
expect(state.fetch(uid)).to eq(nil)
|
26
|
+
end
|
27
|
+
it "returns data" do
|
28
|
+
state = State.instance
|
29
|
+
uid = SecureRandom.uuid
|
30
|
+
data = { data: {} }
|
31
|
+
state.store(uid, data.to_json)
|
32
|
+
expect(state.fetch(uid)).to eq(data.to_json)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#exists?" do
|
37
|
+
it "returns data" do
|
38
|
+
state = State.instance
|
39
|
+
uid = SecureRandom.uuid
|
40
|
+
expect(state.exists?(uid)).to eq(false)
|
41
|
+
end
|
42
|
+
it "returns data" do
|
43
|
+
state = State.instance
|
44
|
+
uid = SecureRandom.uuid
|
45
|
+
data = { data: {} }
|
46
|
+
state.store(uid, data.to_json)
|
47
|
+
expect(state.exists?(uid)).to eq(true)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#delete" do
|
52
|
+
it "returns data" do
|
53
|
+
state = State.instance
|
54
|
+
uid = SecureRandom.uuid
|
55
|
+
expect(state.delete(uid)).to eq(0)
|
56
|
+
end
|
57
|
+
it "returns data" do
|
58
|
+
state = State.instance
|
59
|
+
uid = SecureRandom.uuid
|
60
|
+
data = { data: {} }
|
61
|
+
state.store(uid, data.to_json)
|
62
|
+
expect(state.delete(uid)).to eq(1)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|