stealth 0.9.1
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 +7 -0
- data/.circleci/config.yml +58 -0
- data/.gitignore +12 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +81 -0
- data/LICENSE +20 -0
- data/README.md +1 -0
- data/VERSION +1 -0
- data/bin/stealth +5 -0
- data/lib/stealth/base.rb +87 -0
- data/lib/stealth/cli.rb +82 -0
- data/lib/stealth/cli_base.rb +25 -0
- data/lib/stealth/commands/command.rb +14 -0
- data/lib/stealth/commands/console.rb +75 -0
- data/lib/stealth/commands/server.rb +20 -0
- data/lib/stealth/configuration.rb +54 -0
- data/lib/stealth/controller.rb +190 -0
- data/lib/stealth/dispatcher.rb +48 -0
- data/lib/stealth/errors.rb +32 -0
- data/lib/stealth/flow/base.rb +256 -0
- data/lib/stealth/flow/errors.rb +25 -0
- data/lib/stealth/flow/event.rb +43 -0
- data/lib/stealth/flow/event_collection.rb +41 -0
- data/lib/stealth/flow/specification.rb +67 -0
- data/lib/stealth/flow/state.rb +48 -0
- data/lib/stealth/jobs.rb +10 -0
- data/lib/stealth/logger.rb +16 -0
- data/lib/stealth/reply.rb +19 -0
- data/lib/stealth/server.rb +38 -0
- data/lib/stealth/service_message.rb +17 -0
- data/lib/stealth/service_reply.rb +30 -0
- data/lib/stealth/services/base_client.rb +28 -0
- data/lib/stealth/services/base_message_handler.rb +28 -0
- data/lib/stealth/services/base_reply_handler.rb +65 -0
- data/lib/stealth/services/facebook/client.rb +35 -0
- data/lib/stealth/services/facebook/events/message_event.rb +59 -0
- data/lib/stealth/services/facebook/events/postback_event.rb +36 -0
- data/lib/stealth/services/facebook/message_handler.rb +84 -0
- data/lib/stealth/services/facebook/reply_handler.rb +471 -0
- data/lib/stealth/services/facebook/setup.rb +25 -0
- data/lib/stealth/services/jobs/handle_message_job.rb +22 -0
- data/lib/stealth/session.rb +74 -0
- data/lib/stealth/version.rb +12 -0
- data/lib/stealth.rb +1 -0
- data/spec/configuration_spec.rb +52 -0
- data/spec/flow/custom_transitions_spec.rb +99 -0
- data/spec/flow/flow_spec.rb +91 -0
- data/spec/flow/transition_callbacks_spec.rb +228 -0
- data/spec/replies/nested_reply_with_erb.yml +16 -0
- data/spec/sample_services_yml/services.yml +31 -0
- data/spec/sample_services_yml/services_with_erb.yml +31 -0
- data/spec/service_reply_spec.rb +34 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/version_spec.rb +16 -0
- data/stealth.gemspec +30 -0
- metadata +247 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
4
|
+
|
5
|
+
describe "custom transitions" do
|
6
|
+
|
7
|
+
class FetchTodosFlow
|
8
|
+
include Stealth::Flow
|
9
|
+
|
10
|
+
flow do
|
11
|
+
state :todays_todos do
|
12
|
+
event :fetch_tomorrows_todos, :transitions_to => :tomorrows_todos
|
13
|
+
event :fetch_yesterdays_todos, :transitions_to => :yesterdays_todos
|
14
|
+
end
|
15
|
+
|
16
|
+
state :tomorrows_todos do
|
17
|
+
event :view_todo, :transitions_to => :show
|
18
|
+
event :edit_todo, :transitions_to => :edit
|
19
|
+
end
|
20
|
+
|
21
|
+
state :tomorrows_todos do
|
22
|
+
event :view_todo, :transitions_to => :show
|
23
|
+
event :edit_todo, :transitions_to => :edit
|
24
|
+
end
|
25
|
+
|
26
|
+
state :show
|
27
|
+
|
28
|
+
state :edit do
|
29
|
+
event :save_todo, :transitions_to => :show
|
30
|
+
event :error_in_input, :transitions_to => :error
|
31
|
+
end
|
32
|
+
|
33
|
+
state :error
|
34
|
+
end
|
35
|
+
|
36
|
+
def view_todo(todo_id)
|
37
|
+
unless todo_id > 0
|
38
|
+
halt('ID is not valid.')
|
39
|
+
end
|
40
|
+
|
41
|
+
:the_todo
|
42
|
+
end
|
43
|
+
|
44
|
+
def edit_todo(todo_id)
|
45
|
+
unless todo_id > 0
|
46
|
+
halt('ID is not valid.')
|
47
|
+
end
|
48
|
+
|
49
|
+
:edit_todo_view
|
50
|
+
end
|
51
|
+
|
52
|
+
def save_todo(params)
|
53
|
+
if params.nil?
|
54
|
+
halt!('Invalid todo params specified.')
|
55
|
+
end
|
56
|
+
|
57
|
+
:todo_saved
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
let(:flow) { FetchTodosFlow.new }
|
62
|
+
|
63
|
+
it "should transition via custom transition methods" do
|
64
|
+
flow.fetch_tomorrows_todos!
|
65
|
+
expect(flow.view_todo!(1)).to eq :the_todo
|
66
|
+
expect(flow.current_state).to eq :show
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should follow multiple custom transitions" do
|
70
|
+
flow.fetch_tomorrows_todos!
|
71
|
+
expect(flow.edit_todo!(1)).to eq :edit_todo_view
|
72
|
+
expect(flow.current_state).to eq :edit
|
73
|
+
|
74
|
+
expect(flow.save_todo!({ task: 'test' })).to eq :todo_saved
|
75
|
+
expect(flow.current_state).to eq :show
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "halting transitions" do
|
79
|
+
it "should halt the transition when halt() is called" do
|
80
|
+
flow.fetch_tomorrows_todos!
|
81
|
+
flow.view_todo!(-1)
|
82
|
+
expect(flow.current_state).to eq :tomorrows_todos
|
83
|
+
expect(flow.halted_because).to eq "ID is not valid."
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should halt the transition when halt!() is called and raise Stealth::Flow::TransitionHalted" do
|
87
|
+
flow.fetch_tomorrows_todos!
|
88
|
+
flow.edit_todo!(1)
|
89
|
+
expect(flow.current_state).to eq :edit
|
90
|
+
|
91
|
+
expect {
|
92
|
+
flow.save_todo!(nil)
|
93
|
+
}.to raise_error(Stealth::Flow::TransitionHalted)
|
94
|
+
|
95
|
+
expect(flow.halted_because).to eq "Invalid todo params specified."
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
4
|
+
|
5
|
+
describe Stealth::Flow do
|
6
|
+
|
7
|
+
class NewTodoFlow
|
8
|
+
include Stealth::Flow
|
9
|
+
|
10
|
+
flow do
|
11
|
+
state :new do
|
12
|
+
event :submit_todo, :transitions_to => :get_due_date
|
13
|
+
event :error_in_input, :transitions_to => :error
|
14
|
+
end
|
15
|
+
|
16
|
+
state :get_due_date do
|
17
|
+
event :submit_due_date, :transitions_to => :created
|
18
|
+
end
|
19
|
+
|
20
|
+
state :created
|
21
|
+
|
22
|
+
state :error do
|
23
|
+
event :submit_todo, :transitions_to => :get_due_date
|
24
|
+
event :error_in_input, :transitions_to => :error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:flow) { NewTodoFlow.new }
|
30
|
+
|
31
|
+
describe "state transitions" do
|
32
|
+
it "should start out in the 'new' state" do
|
33
|
+
expect(flow.current_state).to eq :new
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should transition into the 'get_due_date' state after submit" do
|
37
|
+
flow.submit_todo!
|
38
|
+
expect(flow.current_state).to eq :get_due_date
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should transition into the 'error' state after error_in_input" do
|
42
|
+
flow.error_in_input!
|
43
|
+
expect(flow.current_state).to eq :error
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should transition through multiple states" do
|
47
|
+
flow.submit_todo!
|
48
|
+
flow.submit_due_date!
|
49
|
+
expect(flow.current_state).to eq :created
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should remain in the error state" do
|
53
|
+
flow.error_in_input!
|
54
|
+
expect(flow.current_state).to eq :error
|
55
|
+
flow.error_in_input!
|
56
|
+
expect(flow.current_state).to eq :error
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should be false when checking the possibility of a non-valid transition" do
|
60
|
+
expect(flow.can_submit_due_date?).to be false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should be false when checking the possibility of a valid transition" do
|
64
|
+
flow.submit_todo!
|
65
|
+
expect(flow.can_submit_due_date?).to be true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "accessing states" do
|
70
|
+
it "should start out in the 'new' state" do
|
71
|
+
expect(flow.new?).to be true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should support comparing states" do
|
75
|
+
first_state = NewTodoFlow.flow_spec.states[:new]
|
76
|
+
last_state = NewTodoFlow.flow_spec.states[:error]
|
77
|
+
expect(first_state < last_state).to be true
|
78
|
+
expect(last_state > first_state).to be true
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should allow every state to be fetched for the class" do
|
82
|
+
expect(NewTodoFlow.flow_spec.states.length).to eq 4
|
83
|
+
expect(NewTodoFlow.flow_spec.states.keys).to eq([:new, :get_due_date, :created, :error])
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return the states in an array for a given flow instance" do
|
87
|
+
expect(flow.states).to eq [:new, :get_due_date, :created, :error]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
4
|
+
|
5
|
+
describe "transition callbacks" do
|
6
|
+
|
7
|
+
class KonamiCodeFlow
|
8
|
+
include Stealth::Flow
|
9
|
+
|
10
|
+
attr_reader :code, :before_transition_count, :transition_count
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@code = []
|
14
|
+
@before_transition_count = 0
|
15
|
+
@transition_count = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
flow do
|
19
|
+
state :up do
|
20
|
+
event :upward, :transitions_to => :up
|
21
|
+
event :downward, :transitions_to => :down
|
22
|
+
end
|
23
|
+
|
24
|
+
state :down do
|
25
|
+
event :downward, :transitions_to => :down
|
26
|
+
event :leftward, :transitions_to => :left
|
27
|
+
end
|
28
|
+
|
29
|
+
state :left do
|
30
|
+
event :rightward, :transitions_to => :right
|
31
|
+
end
|
32
|
+
|
33
|
+
state :right do
|
34
|
+
event :leftward, :transitions_to => :left
|
35
|
+
event :bward, :transitions_to => :b
|
36
|
+
end
|
37
|
+
|
38
|
+
state :a
|
39
|
+
|
40
|
+
state :b do
|
41
|
+
event :award, :transitions_to => :a
|
42
|
+
end
|
43
|
+
|
44
|
+
before_transition do |from, to, triggering_event, *event_args|
|
45
|
+
@before_transition_count += 1
|
46
|
+
end
|
47
|
+
|
48
|
+
after_transition do |from, to, triggering_event, *event_args|
|
49
|
+
@code << to.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
on_transition {
|
53
|
+
@transition_count += 1
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
let(:flow) { KonamiCodeFlow.new }
|
59
|
+
|
60
|
+
before(:each) do
|
61
|
+
flow.upward!
|
62
|
+
flow.upward!
|
63
|
+
flow.downward!
|
64
|
+
flow.downward!
|
65
|
+
flow.leftward!
|
66
|
+
flow.rightward!
|
67
|
+
flow.leftward!
|
68
|
+
flow.rightward!
|
69
|
+
flow.bward!
|
70
|
+
flow.award!
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should have a correct transition count" do
|
74
|
+
expect(flow.transition_count).to eq 10
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should have a correct before_transition count" do
|
78
|
+
expect(flow.before_transition_count).to eq 10
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should have generated the correct code via after_transition" do
|
82
|
+
expect(flow.code).to eq(['up', 'up', 'down', 'down', 'left', 'right', 'left', 'right', 'b', 'a'])
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "on_error callbacks" do
|
86
|
+
class ErrorFlow
|
87
|
+
include Stealth::Flow
|
88
|
+
|
89
|
+
attr_reader :errors
|
90
|
+
|
91
|
+
def initialize
|
92
|
+
@errors = {}
|
93
|
+
end
|
94
|
+
|
95
|
+
flow do
|
96
|
+
state :first do
|
97
|
+
event :advance, :transitions_to => :second do
|
98
|
+
raise "uh oh"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
state :second
|
103
|
+
|
104
|
+
on_error do |error, from, to, event, *args|
|
105
|
+
@errors.merge!({
|
106
|
+
error: error.class,
|
107
|
+
from: from,
|
108
|
+
to: to,
|
109
|
+
event: event,
|
110
|
+
args: args
|
111
|
+
})
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
let(:error_flow) { ErrorFlow.new }
|
117
|
+
|
118
|
+
it "should not advance to the next state" do
|
119
|
+
error_flow.advance!
|
120
|
+
expect(error_flow.current_state).to eq :first
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should call the on_error block" do
|
124
|
+
error_flow.advance!
|
125
|
+
expect(error_flow.errors).to eq({ error: RuntimeError, from: :first, to: :second, event: :advance, args: [] })
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "on_entry and on_exit callbacks" do
|
130
|
+
class PostFlow
|
131
|
+
include Stealth::Flow
|
132
|
+
|
133
|
+
attr_reader :email_reviewer, :tweet_link
|
134
|
+
|
135
|
+
def initialize
|
136
|
+
@email_reviewer = false
|
137
|
+
@tweet_link = false
|
138
|
+
end
|
139
|
+
|
140
|
+
flow do
|
141
|
+
state :draft do
|
142
|
+
event :submit_for_review, :transitions_to => :in_review
|
143
|
+
|
144
|
+
on_exit do
|
145
|
+
@email_reviewer = true
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
state :in_review do
|
150
|
+
event :approve, :transitions_to => :live
|
151
|
+
event :reject, :transitions_to => :draft
|
152
|
+
end
|
153
|
+
|
154
|
+
state :live do
|
155
|
+
on_entry do
|
156
|
+
@tweet_link = true
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
let(:post_flow) { PostFlow.new }
|
163
|
+
|
164
|
+
it "should email the reviewer when flow transitions (on_exit) to in_review" do
|
165
|
+
expect {
|
166
|
+
post_flow.submit_for_review!
|
167
|
+
}.to change(post_flow, :email_reviewer).from(false).to(true)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should tweet the post link when flow transitions (on_entry) to live" do
|
171
|
+
post_flow.submit_for_review!
|
172
|
+
|
173
|
+
expect {
|
174
|
+
post_flow.approve!
|
175
|
+
}.to change(post_flow, :tweet_link).from(false).to(true)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "on_entry and on_exit method-style callbacks" do
|
180
|
+
class ConcisePostFlow
|
181
|
+
include Stealth::Flow
|
182
|
+
|
183
|
+
attr_reader :email_reviewer, :tweet_link
|
184
|
+
|
185
|
+
def initialize
|
186
|
+
@email_reviewer = false
|
187
|
+
@tweet_link = false
|
188
|
+
end
|
189
|
+
|
190
|
+
flow do
|
191
|
+
state :draft do
|
192
|
+
event :submit_for_review, :transitions_to => :in_review
|
193
|
+
end
|
194
|
+
|
195
|
+
state :in_review do
|
196
|
+
event :approve, :transitions_to => :live
|
197
|
+
event :reject, :transitions_to => :draft
|
198
|
+
end
|
199
|
+
|
200
|
+
state :live
|
201
|
+
end
|
202
|
+
|
203
|
+
def on_draft_exit(new_state, event, *args)
|
204
|
+
@email_reviewer = true
|
205
|
+
end
|
206
|
+
|
207
|
+
def on_live_entry(prior_state, event, *args)
|
208
|
+
@tweet_link = true
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
let(:post_flow) { ConcisePostFlow.new }
|
213
|
+
|
214
|
+
it "should email the reviewer when flow transitions (on_exit) to in_review" do
|
215
|
+
expect {
|
216
|
+
post_flow.submit_for_review!
|
217
|
+
}.to change(post_flow, :email_reviewer).from(false).to(true)
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should tweet the post link when flow transitions (on_entry) to live" do
|
221
|
+
post_flow.submit_for_review!
|
222
|
+
|
223
|
+
expect {
|
224
|
+
post_flow.approve!
|
225
|
+
}.to change(post_flow, :tweet_link).from(false).to(true)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
- reply_type: text
|
2
|
+
text: "Hi, <%= first_name %>. Welcome to Stealth bot..."
|
3
|
+
- reply-type: delay
|
4
|
+
duration: 2
|
5
|
+
- reply_type: text
|
6
|
+
text: "We offer users an awesome Ruby framework for building chat bots."
|
7
|
+
- reply-type: delay
|
8
|
+
duration: 2
|
9
|
+
- reply_type: text
|
10
|
+
text: "What do you think of our bot?"
|
11
|
+
buttons:
|
12
|
+
- text: "Cool"
|
13
|
+
payload: cool
|
14
|
+
- text: "Show me more"
|
15
|
+
payload: more
|
16
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
default: &default
|
2
|
+
facebook:
|
3
|
+
verify_token: c68823f4-7259-4600-b9f0-382a67260757
|
4
|
+
challenge: pOmQ7iq4ZA1hK6TbO7yrVZCmygVjfIiEIYaIZAlEveOAzY4UKb
|
5
|
+
page_access_token: EAADhbJruBbMBAKY9bnesHh9eM09ZAHjGsCQtNdvuZClZCFtyIXdFdIQI2mV0PJM910Qyn3lNNhZBPZB54zLRhDNmeIkDz9myS25CTy0kFxHjQCXJxz5oeZCD60VWdAZAFxbeDKvF8eF28qDHAI4wkGc3jvVhjFISKmmFRRM6goUeAZDZD
|
6
|
+
setup:
|
7
|
+
greeting: # Greetings are broken up by locale
|
8
|
+
- locale: default
|
9
|
+
text: "Welcome to the Stealth bot 🤖"
|
10
|
+
persistent_menu:
|
11
|
+
- type: payload
|
12
|
+
text: Main Menu
|
13
|
+
payload: main_menu
|
14
|
+
- type: url
|
15
|
+
text: Visit our website
|
16
|
+
url: https://example.com
|
17
|
+
- type: call
|
18
|
+
text: Call us
|
19
|
+
payload: "+17345551234"
|
20
|
+
twilio_sms:
|
21
|
+
account_sid: BC6f4bd46307054c84fdff70badcd9ef5d
|
22
|
+
auth_token: 4af73d27d92cff6391611a9c976725cc
|
23
|
+
|
24
|
+
production:
|
25
|
+
<<: *default
|
26
|
+
|
27
|
+
development:
|
28
|
+
<<: *default
|
29
|
+
|
30
|
+
test:
|
31
|
+
<<: *default
|
@@ -0,0 +1,31 @@
|
|
1
|
+
default: &default
|
2
|
+
facebook:
|
3
|
+
verify_token: <%= ENV['FACEBOOK_VERIFY_TOKEN'] %>
|
4
|
+
challenge: <%= ENV['FACEBOOK_CHALLENGE'] %>
|
5
|
+
page_access_token: <%= ENV['FACEBOOK_PAGE_ACCESS_TOKEN'] %>
|
6
|
+
setup:
|
7
|
+
greeting: # Greetings are broken up by locale
|
8
|
+
- locale: default
|
9
|
+
text: "Welcome to the Stealth bot 🤖"
|
10
|
+
persistent_menu:
|
11
|
+
- type: payload
|
12
|
+
text: Main Menu
|
13
|
+
payload: main_menu
|
14
|
+
- type: url
|
15
|
+
text: Visit our website
|
16
|
+
url: https://example.com
|
17
|
+
- type: call
|
18
|
+
text: Call us
|
19
|
+
payload: "+17345551234"
|
20
|
+
twilio_sms:
|
21
|
+
account_sid: <%= ENV['TWILIO_ACCOUNT_SID'] %>
|
22
|
+
auth_token: <%= ENV['TWILIO_AUTH_TOKEN'] %>
|
23
|
+
|
24
|
+
production:
|
25
|
+
<<: *default
|
26
|
+
|
27
|
+
development:
|
28
|
+
<<: *default
|
29
|
+
|
30
|
+
test:
|
31
|
+
<<: *default
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
4
|
+
|
5
|
+
describe "Stealth::ServiceReply" do
|
6
|
+
|
7
|
+
describe "nested reply with ERB" do
|
8
|
+
let(:recipient_id) { "8b3e0a3c-62f1-401e-8b0f-615c9d256b1f" }
|
9
|
+
let(:yaml_reply) { File.read(File.join(File.dirname(__FILE__), 'replies', 'nested_reply_with_erb.yml')) }
|
10
|
+
|
11
|
+
it "should load all the replies" do
|
12
|
+
first_name = "Presley"
|
13
|
+
|
14
|
+
service_reply = Stealth::ServiceReply.new(
|
15
|
+
recipient_id: recipient_id,
|
16
|
+
yaml_reply: yaml_reply,
|
17
|
+
context: binding
|
18
|
+
)
|
19
|
+
|
20
|
+
expect(service_reply.replies.size).to eq 5
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should raise Stealth::Errors::UndefinedVariable when local variable is not available" do
|
24
|
+
expect {
|
25
|
+
service_reply = Stealth::ServiceReply.new(
|
26
|
+
recipient_id: recipient_id,
|
27
|
+
yaml_reply: yaml_reply,
|
28
|
+
context: binding
|
29
|
+
)
|
30
|
+
}.to raise_error(Stealth::Errors::UndefinedVariable)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
|
5
|
+
require 'stealth'
|
6
|
+
|
7
|
+
# Requires supporting files with custom matchers and macros, etc,
|
8
|
+
# in ./support/ and its subdirectories.
|
9
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
4
|
+
|
5
|
+
describe "Stealth::Version" do
|
6
|
+
|
7
|
+
let(:version_in_file) { File.read(File.join(File.dirname(__FILE__), '..', 'VERSION')).strip }
|
8
|
+
|
9
|
+
it "should return the current gem version" do
|
10
|
+
expect(Stealth::Version.version).to eq version_in_file
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return the current gem version via a constant" do
|
14
|
+
expect(Stealth::VERSION).to eq version_in_file
|
15
|
+
end
|
16
|
+
end
|
data/stealth.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
|
+
|
3
|
+
version = File.read(File.join(File.dirname(__FILE__), 'VERSION')).strip
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'stealth'
|
7
|
+
s.summary = 'Ruby framework for conversational bots'
|
8
|
+
s.description = 'Ruby framework for building conversational bots.'
|
9
|
+
s.homepage = 'https://github.com/whoisblackops/stealth'
|
10
|
+
s.version = version
|
11
|
+
s.author = 'Mauricio Gomes'
|
12
|
+
s.email = 'mauricio@edge14.com'
|
13
|
+
|
14
|
+
s.add_dependency 'sinatra', '~> 2.0.0'
|
15
|
+
s.add_dependency 'puma', '~> 3.10.0'
|
16
|
+
s.add_dependency 'thor', '~> 0.20'
|
17
|
+
s.add_dependency 'multi_json', '~> 1.12'
|
18
|
+
s.add_dependency 'faraday', '~> 0.13'
|
19
|
+
s.add_dependency 'sidekiq', '~> 5.0'
|
20
|
+
s.add_dependency 'activesupport', '~> 5.1'
|
21
|
+
|
22
|
+
s.add_development_dependency 'rspec', '~> 3.6.0'
|
23
|
+
s.add_development_dependency 'rspec_junit_formatter', '~> 0.3.0'
|
24
|
+
s.add_development_dependency 'rack-test', '~> 0.7.0'
|
25
|
+
|
26
|
+
s.files = `git ls-files`.split("\n")
|
27
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
28
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
29
|
+
s.require_paths = ['lib']
|
30
|
+
end
|