stealth 1.0.4 → 1.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +32 -77
- data/README.md +1 -0
- data/VERSION +1 -1
- data/docs/03-basics.md +18 -2
- data/docs/04-sessions.md +12 -0
- data/docs/05-controllers.md +3 -3
- data/docs/07-replies.md +42 -1
- data/lib/stealth/base.rb +23 -9
- data/lib/stealth/controller/catch_all.rb +1 -1
- data/lib/stealth/controller/controller.rb +21 -9
- data/lib/stealth/controller/dynamic_delay.rb +64 -0
- data/lib/stealth/controller/replies.rb +55 -14
- data/lib/stealth/flow/base.rb +1 -1
- data/lib/stealth/flow/specification.rb +30 -8
- data/lib/stealth/flow/state.rb +10 -5
- data/lib/stealth/generators/builder/Gemfile +3 -0
- data/lib/stealth/generators/builder/Procfile.dev +1 -1
- data/lib/stealth/generators/builder/bot/controllers/catch_alls_controller.rb +3 -6
- data/lib/stealth/generators/builder/config/services.yml +9 -10
- data/lib/stealth/generators/generate/flow/controllers/controller.tt +0 -19
- data/lib/stealth/generators/generate/flow/helpers/helper.tt +2 -1
- data/lib/stealth/generators/generate/flow/replies/{ask_reply.tt → ask_example.tt} +0 -0
- data/lib/stealth/generators/generate.rb +2 -9
- data/lib/stealth/migrations/tasks.rb +2 -0
- data/lib/stealth/scheduled_reply.rb +1 -1
- data/lib/stealth/server.rb +2 -0
- data/lib/stealth/services/jobs/handle_message_job.rb +1 -1
- data/lib/stealth/session.rb +44 -16
- data/spec/controller/catch_all_spec.rb +2 -1
- data/spec/controller/controller_spec.rb +102 -13
- data/spec/controller/dynamic_delay_spec.rb +72 -0
- data/spec/controller/replies_spec.rb +94 -3
- data/spec/flow/state_spec.rb +33 -4
- data/spec/replies/messages/say_hola.yml+facebook.erb +6 -0
- data/spec/replies/messages/say_hola.yml+twilio.erb +6 -0
- data/spec/replies/messages/say_hola.yml.erb +6 -0
- data/spec/replies/messages/say_howdy_with_dynamic.yml +79 -0
- data/spec/replies/messages/say_offer_with_dynamic.yml +6 -0
- data/spec/replies/messages/say_yo.yml +6 -0
- data/spec/replies/messages/say_yo.yml+twitter +6 -0
- data/spec/session_spec.rb +17 -0
- data/spec/support/sample_messages.rb +24 -26
- data/stealth.gemspec +1 -3
- metadata +25 -41
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -17
- data/lib/stealth/generators/generate/flow/models/model.tt +0 -2
- data/lib/stealth/generators/generate/flow/replies/say_no_reply.tt +0 -2
- data/lib/stealth/generators/generate/flow/replies/say_yes_reply.tt +0 -2
@@ -46,12 +46,101 @@ describe "Stealth::Controller" do
|
|
46
46
|
state :other_action
|
47
47
|
state :other_action2
|
48
48
|
state :other_action3
|
49
|
+
state :deprecated_action, redirects_to: :other_action
|
50
|
+
state :deprecated_action2, redirects_to: 'mr_robot->my_action'
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
54
|
let(:facebook_message) { SampleMessage.new(service: 'facebook') }
|
53
55
|
let(:controller) { MrTronsController.new(service_message: facebook_message.message_with_text) }
|
54
56
|
|
57
|
+
describe "convenience methods" do
|
58
|
+
it "should make the session ID accessible via current_session_id" do
|
59
|
+
controller.current_session.set(flow: 'mr_tron', state: 'other_action')
|
60
|
+
|
61
|
+
expect(controller.current_session_id).to eq(facebook_message.sender_id)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should make the session ID accessible via current_user_id" do
|
65
|
+
controller.current_session.set(flow: 'mr_tron', state: 'other_action')
|
66
|
+
|
67
|
+
expect(controller.current_user_id).to eq(facebook_message.sender_id)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should make the message available in current_message.message" do
|
71
|
+
expect(controller.current_message.message).to eq(facebook_message.message)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should make the payload available in current_message.payload" do
|
75
|
+
message_with_payload = facebook_message.message_with_payload
|
76
|
+
expect(controller.current_message.payload).to eq(message_with_payload.payload)
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "current_service" do
|
80
|
+
let(:twilio_message) { SampleMessage.new(service: 'twilio') }
|
81
|
+
let(:controller_with_twilio_message) { MrTronsController.new(service_message: twilio_message.message_with_text) }
|
82
|
+
|
83
|
+
it "should detect a Facebook message" do
|
84
|
+
expect(controller.current_service).to eq('facebook')
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should detect a Twilio message" do
|
88
|
+
expect(controller_with_twilio_message.current_service).to eq('twilio')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "messages with location" do
|
93
|
+
let(:message_with_location) { facebook_message.message_with_location }
|
94
|
+
let(:controller_with_location) { MrTronsController.new(service_message: message_with_location) }
|
95
|
+
|
96
|
+
it "should make the location available in current_message.location" do
|
97
|
+
expect(controller_with_location.current_message.location).to eq(message_with_location.location)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should return true for current_message.has_location?" do
|
101
|
+
expect(controller_with_location.has_location?).to be true
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "messages with attachments" do
|
106
|
+
let(:message_with_attachments) { facebook_message.message_with_attachments }
|
107
|
+
let(:controller_with_attachment) { MrTronsController.new(service_message: message_with_attachments) }
|
108
|
+
|
109
|
+
it "should make the attachments available in current_message.attachments" do
|
110
|
+
expect(controller_with_attachment.current_message.attachments).to eq(message_with_attachments.attachments)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should return true for current_message.has_attachments?" do
|
114
|
+
expect(controller_with_attachment.has_attachments?).to be true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "states with redirect_to specified" do
|
120
|
+
it "should step_to the specified redirect state when only a state is specified" do
|
121
|
+
controller.current_session.session = Stealth::Session.canonical_session_slug(flow: 'mr_tron', state: 'deprecated_action')
|
122
|
+
expect(MrTronsController).to receive(:new).and_return(controller)
|
123
|
+
expect(controller).to receive(:other_action)
|
124
|
+
controller.action(action: :deprecated_action)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should step_to the specified redirect flow and state when a session is specified" do
|
128
|
+
controller.current_session.session = Stealth::Session.canonical_session_slug(flow: 'mr_tron', state: 'deprecated_action2')
|
129
|
+
mr_robot_controller = MrTronsController.new(service_message: facebook_message.message_with_text)
|
130
|
+
|
131
|
+
expect(MrRobotsController).to receive(:new).and_return(mr_robot_controller)
|
132
|
+
expect(mr_robot_controller).to receive(:my_action)
|
133
|
+
controller.action(action: :deprecated_action2)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should NOT call the redirected controller action method" do
|
137
|
+
controller.current_session.session = Stealth::Session.canonical_session_slug(flow: 'mr_tron', state: 'deprecated_action')
|
138
|
+
expect(MrTronsController).to receive(:new).and_return(controller)
|
139
|
+
expect(controller).to_not receive(:deprecated_action)
|
140
|
+
controller.action(action: :deprecated_action)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
55
144
|
describe "step_to" do
|
56
145
|
it "should raise an ArgumentError if a session, flow, or state is not specified" do
|
57
146
|
expect {
|
@@ -128,7 +217,7 @@ describe "Stealth::Controller" do
|
|
128
217
|
it "should update session to controller's corresponding action when a session is provided" do
|
129
218
|
expect_any_instance_of(MrRobotsController).to_not receive(:my_action3)
|
130
219
|
|
131
|
-
session = Stealth::Session.new(user_id: controller.
|
220
|
+
session = Stealth::Session.new(user_id: controller.current_session_id)
|
132
221
|
session.set(flow: 'mr_robot', state: 'my_action3')
|
133
222
|
|
134
223
|
controller.update_session_to session: session
|
@@ -164,7 +253,7 @@ describe "Stealth::Controller" do
|
|
164
253
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_in).with(
|
165
254
|
100.seconds,
|
166
255
|
controller.current_service,
|
167
|
-
controller.
|
256
|
+
controller.current_session_id,
|
168
257
|
'mr_robot',
|
169
258
|
'my_action'
|
170
259
|
)
|
@@ -182,7 +271,7 @@ describe "Stealth::Controller" do
|
|
182
271
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_in).with(
|
183
272
|
100.seconds,
|
184
273
|
controller.current_service,
|
185
|
-
controller.
|
274
|
+
controller.current_session_id,
|
186
275
|
'mr_tron',
|
187
276
|
'other_action3'
|
188
277
|
)
|
@@ -198,7 +287,7 @@ describe "Stealth::Controller" do
|
|
198
287
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_in).with(
|
199
288
|
100.seconds,
|
200
289
|
controller.current_service,
|
201
|
-
controller.
|
290
|
+
controller.current_session_id,
|
202
291
|
'mr_robot',
|
203
292
|
'my_action3'
|
204
293
|
)
|
@@ -211,13 +300,13 @@ describe "Stealth::Controller" do
|
|
211
300
|
it "should update session to controller's corresponding action when a session is provided" do
|
212
301
|
expect_any_instance_of(MrRobotsController).to_not receive(:my_action)
|
213
302
|
|
214
|
-
session = Stealth::Session.new(user_id: controller.
|
303
|
+
session = Stealth::Session.new(user_id: controller.current_session_id)
|
215
304
|
session.set(flow: 'mr_robot', state: 'my_action3')
|
216
305
|
|
217
306
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_in).with(
|
218
307
|
100.seconds,
|
219
308
|
controller.current_service,
|
220
|
-
controller.
|
309
|
+
controller.current_session_id,
|
221
310
|
'mr_robot',
|
222
311
|
'my_action3'
|
223
312
|
)
|
@@ -233,7 +322,7 @@ describe "Stealth::Controller" do
|
|
233
322
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_in).with(
|
234
323
|
100.seconds,
|
235
324
|
controller.current_service,
|
236
|
-
controller.
|
325
|
+
controller.current_session_id,
|
237
326
|
'mr_robot',
|
238
327
|
'my_action3'
|
239
328
|
)
|
@@ -265,7 +354,7 @@ describe "Stealth::Controller" do
|
|
265
354
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_at).with(
|
266
355
|
future_timestamp,
|
267
356
|
controller.current_service,
|
268
|
-
controller.
|
357
|
+
controller.current_session_id,
|
269
358
|
'mr_robot',
|
270
359
|
'my_action'
|
271
360
|
)
|
@@ -283,7 +372,7 @@ describe "Stealth::Controller" do
|
|
283
372
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_at).with(
|
284
373
|
future_timestamp,
|
285
374
|
controller.current_service,
|
286
|
-
controller.
|
375
|
+
controller.current_session_id,
|
287
376
|
'mr_tron',
|
288
377
|
'other_action3'
|
289
378
|
)
|
@@ -299,7 +388,7 @@ describe "Stealth::Controller" do
|
|
299
388
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_at).with(
|
300
389
|
future_timestamp,
|
301
390
|
controller.current_service,
|
302
|
-
controller.
|
391
|
+
controller.current_session_id,
|
303
392
|
'mr_robot',
|
304
393
|
'my_action3'
|
305
394
|
)
|
@@ -312,13 +401,13 @@ describe "Stealth::Controller" do
|
|
312
401
|
it "should update session to controller's corresponding action when a session is provided" do
|
313
402
|
expect_any_instance_of(MrRobotsController).to_not receive(:my_action)
|
314
403
|
|
315
|
-
session = Stealth::Session.new(user_id: controller.
|
404
|
+
session = Stealth::Session.new(user_id: controller.current_session_id)
|
316
405
|
session.set(flow: 'mr_robot', state: 'my_action3')
|
317
406
|
|
318
407
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_at).with(
|
319
408
|
future_timestamp,
|
320
409
|
controller.current_service,
|
321
|
-
controller.
|
410
|
+
controller.current_session_id,
|
322
411
|
'mr_robot',
|
323
412
|
'my_action3'
|
324
413
|
)
|
@@ -334,7 +423,7 @@ describe "Stealth::Controller" do
|
|
334
423
|
expect(Stealth::ScheduledReplyJob).to receive(:perform_at).with(
|
335
424
|
future_timestamp,
|
336
425
|
controller.current_service,
|
337
|
-
controller.
|
426
|
+
controller.current_session_id,
|
338
427
|
'mr_robot',
|
339
428
|
'my_action3'
|
340
429
|
)
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '/spec_helper'))
|
5
|
+
|
6
|
+
describe "Stealth::Controller::DynamicDelay" do
|
7
|
+
|
8
|
+
let(:facebook_message) { SampleMessage.new(service: 'facebook') }
|
9
|
+
let(:controller) { VadersController.new(service_message: facebook_message.message_with_text) }
|
10
|
+
let(:service_replies) { YAML.load(File.read(File.expand_path("../replies/messages/say_howdy_with_dynamic.yml", __dir__))) }
|
11
|
+
|
12
|
+
it "should return a SHORT_DELAY for a dynamic delay at position 0" do
|
13
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 0)
|
14
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::SHORT_DELAY)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return a SHORT_DELAY for a dynamic delay at position -1" do
|
18
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: -1)
|
19
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::SHORT_DELAY)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return a SHORT_DELAY for text 35 chars long" do
|
23
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 2)
|
24
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::SHORT_DELAY)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return a STANDARD_DELAY for text 120 chars long" do
|
28
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 4)
|
29
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::STANDARD_DELAY)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return a (STANDARD_DELAY * 1.5) for text 230 chars long" do
|
33
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 6)
|
34
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::STANDARD_DELAY * 1.5)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return a LONG_DELAY for text 350 chars long" do
|
38
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 8)
|
39
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::LONG_DELAY)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return a STANDARD_DELAY for an image" do
|
43
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 10)
|
44
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::STANDARD_DELAY)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should return a STANDARD_DELAY for a video" do
|
48
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 12)
|
49
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::STANDARD_DELAY)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return a STANDARD_DELAY for an audio" do
|
53
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 14)
|
54
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::STANDARD_DELAY)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return a STANDARD_DELAY for a file" do
|
58
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 16)
|
59
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::STANDARD_DELAY)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return a STANDARD_DELAY for cards" do
|
63
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 18)
|
64
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::STANDARD_DELAY)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return a STANDARD_DELAY for a list" do
|
68
|
+
delay = controller.dynamic_delay(service_replies: service_replies, position: 20)
|
69
|
+
expect(delay).to eq(Stealth::Controller::DynamicDelay::STANDARD_DELAY)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -35,6 +35,10 @@ describe "Stealth::Controller replies" do
|
|
35
35
|
send_replies
|
36
36
|
end
|
37
37
|
|
38
|
+
def say_offer_with_dynamic
|
39
|
+
send_replies
|
40
|
+
end
|
41
|
+
|
38
42
|
def say_uh_oh
|
39
43
|
send_replies
|
40
44
|
end
|
@@ -139,7 +143,7 @@ describe "Stealth::Controller replies" do
|
|
139
143
|
|
140
144
|
it "should translate each reply_type in the reply" do
|
141
145
|
allow(stubbed_client).to receive(:transmit).and_return(true)
|
142
|
-
allow(controller).to receive(:sleep).and_return(true)
|
146
|
+
allow(controller).to receive(:sleep).and_return(true).with(2.0)
|
143
147
|
|
144
148
|
expect(stubbed_handler).to receive(:text).exactly(2).times
|
145
149
|
expect(stubbed_handler).to receive(:delay).exactly(1).times
|
@@ -149,7 +153,7 @@ describe "Stealth::Controller replies" do
|
|
149
153
|
it "should transmit each reply_type in the reply" do
|
150
154
|
allow(stubbed_handler).to receive(:text).exactly(2).times
|
151
155
|
allow(stubbed_handler).to receive(:delay).exactly(1).times
|
152
|
-
allow(controller).to receive(:sleep).and_return(true)
|
156
|
+
allow(controller).to receive(:sleep).and_return(true).with(2.0)
|
153
157
|
|
154
158
|
expect(stubbed_client).to receive(:transmit).exactly(3).times
|
155
159
|
controller.say_offer
|
@@ -160,9 +164,96 @@ describe "Stealth::Controller replies" do
|
|
160
164
|
allow(stubbed_handler).to receive(:delay).exactly(1).times
|
161
165
|
allow(stubbed_client).to receive(:transmit).exactly(3).times
|
162
166
|
|
163
|
-
expect(controller).to receive(:sleep).exactly(1).times
|
167
|
+
expect(controller).to receive(:sleep).exactly(1).times.with(2.0)
|
164
168
|
controller.say_offer
|
165
169
|
end
|
166
170
|
end
|
167
171
|
|
172
|
+
describe "dynamic delays" do
|
173
|
+
let(:stubbed_handler) { double("handler") }
|
174
|
+
let(:stubbed_client) { double("client") }
|
175
|
+
|
176
|
+
before(:each) do
|
177
|
+
allow(Stealth::Services::Facebook::ReplyHandler).to receive(:new).and_return(stubbed_handler)
|
178
|
+
allow(Stealth::Services::Facebook::Client).to receive(:new).and_return(stubbed_client)
|
179
|
+
allow(controller.current_session).to receive(:flow_string).and_return("message")
|
180
|
+
allow(controller.current_session).to receive(:state_string).and_return("say_offer_with_dynamic")
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should use the default multiplier if none is set" do
|
184
|
+
allow(stubbed_handler).to receive(:text).exactly(2).times
|
185
|
+
allow(stubbed_handler).to receive(:delay).exactly(1).times
|
186
|
+
allow(stubbed_client).to receive(:transmit).exactly(3).times
|
187
|
+
|
188
|
+
delay = Stealth.config.dynamic_delay_muliplier * Stealth::Controller::DynamicDelay::SHORT_DELAY
|
189
|
+
expect(controller).to receive(:sleep).exactly(1).times.with(delay)
|
190
|
+
controller.say_offer_with_dynamic
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should slow down SHORT_DELAY if dynamic_delay_muliplier > 1" do
|
194
|
+
allow(stubbed_handler).to receive(:text).exactly(2).times
|
195
|
+
allow(stubbed_handler).to receive(:delay).exactly(1).times
|
196
|
+
allow(stubbed_client).to receive(:transmit).exactly(3).times
|
197
|
+
|
198
|
+
Stealth.config.dynamic_delay_muliplier = 5
|
199
|
+
delay = Stealth.config.dynamic_delay_muliplier * Stealth::Controller::DynamicDelay::SHORT_DELAY
|
200
|
+
expect(controller).to receive(:sleep).exactly(1).times.with(delay)
|
201
|
+
controller.say_offer_with_dynamic
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should speed up SHORT_DELAY if dynamic_delay_muliplier < 1" do
|
205
|
+
allow(stubbed_handler).to receive(:text).exactly(2).times
|
206
|
+
allow(stubbed_handler).to receive(:delay).exactly(1).times
|
207
|
+
allow(stubbed_client).to receive(:transmit).exactly(3).times
|
208
|
+
|
209
|
+
Stealth.config.dynamic_delay_muliplier = 0.1
|
210
|
+
delay = Stealth.config.dynamic_delay_muliplier * Stealth::Controller::DynamicDelay::SHORT_DELAY
|
211
|
+
expect(controller).to receive(:sleep).exactly(1).times.with(delay)
|
212
|
+
controller.say_offer_with_dynamic
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "variants" do
|
217
|
+
let(:twilio_message) { SampleMessage.new(service: 'twilio') }
|
218
|
+
let(:twilio_controller) { MessagesController.new(service_message: twilio_message.message_with_text) }
|
219
|
+
|
220
|
+
let(:epsilon_message) { SampleMessage.new(service: 'epsilon') }
|
221
|
+
let(:epsilon_controller) { MessagesController.new(service_message: epsilon_message.message_with_text) }
|
222
|
+
|
223
|
+
let(:gamma_message) { SampleMessage.new(service: 'twitter') }
|
224
|
+
let(:gamma_controller) { MessagesController.new(service_message: gamma_message.message_with_text) }
|
225
|
+
|
226
|
+
it "should load the Facebook reply variant if current_service == facebook" do
|
227
|
+
allow(controller.current_session).to receive(:flow_string).and_return("message")
|
228
|
+
allow(controller.current_session).to receive(:state_string).and_return("say_hola")
|
229
|
+
file_contents, selected_preprocessor = controller.send(:action_replies)
|
230
|
+
|
231
|
+
expect(file_contents).to eq(File.read(File.expand_path("../replies/messages/say_hola.yml+facebook.erb", __dir__)))
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should load the Twilio reply variant if current_service == twilio" do
|
235
|
+
allow(twilio_controller.current_session).to receive(:flow_string).and_return("message")
|
236
|
+
allow(twilio_controller.current_session).to receive(:state_string).and_return("say_hola")
|
237
|
+
file_contents, selected_preprocessor = twilio_controller.send(:action_replies)
|
238
|
+
|
239
|
+
expect(file_contents).to eq(File.read(File.expand_path("../replies/messages/say_hola.yml+twilio.erb", __dir__)))
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should load the base reply variant if current_service does not have a custom variant" do
|
243
|
+
allow(epsilon_controller.current_session).to receive(:flow_string).and_return("message")
|
244
|
+
allow(epsilon_controller.current_session).to receive(:state_string).and_return("say_hola")
|
245
|
+
file_contents, selected_preprocessor = epsilon_controller.send(:action_replies)
|
246
|
+
|
247
|
+
expect(file_contents).to eq(File.read(File.expand_path("../replies/messages/say_hola.yml.erb", __dir__)))
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should load the correct variant when there is no preprocessor" do
|
251
|
+
allow(gamma_controller.current_session).to receive(:flow_string).and_return("message")
|
252
|
+
allow(gamma_controller.current_session).to receive(:state_string).and_return("say_yo")
|
253
|
+
file_contents, selected_preprocessor = gamma_controller.send(:action_replies)
|
254
|
+
|
255
|
+
expect(file_contents).to eq(File.read(File.expand_path("../replies/messages/say_yo.yml+twitter", __dir__)))
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
168
259
|
end
|
data/spec/flow/state_spec.rb
CHANGED
@@ -12,6 +12,9 @@ describe Stealth::Flow::State do
|
|
12
12
|
state :new
|
13
13
|
state :get_due_date
|
14
14
|
state :created, fails_to: :new
|
15
|
+
state :created2, fails_to: 'new_todo->new'
|
16
|
+
state :deprecated, redirects_to: 'new'
|
17
|
+
state :deprecated2, redirects_to: 'other_flow->say_hi'
|
15
18
|
state :error
|
16
19
|
end
|
17
20
|
end
|
@@ -35,8 +38,34 @@ describe Stealth::Flow::State do
|
|
35
38
|
|
36
39
|
it "should return the fail_state if a fails_to was specified" do
|
37
40
|
flow_map.init(flow: :new_todo, state: :created)
|
38
|
-
expect(flow_map.current_state.fails_to).to be_a(Stealth::
|
39
|
-
expect(flow_map.current_state.fails_to).to eq
|
41
|
+
expect(flow_map.current_state.fails_to).to be_a(Stealth::Session)
|
42
|
+
expect(flow_map.current_state.fails_to.state_string).to eq 'new'
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should return the fail_state if a fails_to was specified as a session" do
|
46
|
+
flow_map.init(flow: :new_todo, state: :created2)
|
47
|
+
expect(flow_map.current_state.fails_to).to be_a(Stealth::Session)
|
48
|
+
expect(flow_map.current_state.fails_to.state_string).to eq 'new'
|
49
|
+
expect(flow_map.current_state.fails_to.flow_string).to eq 'new_todo'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "redirects_to" do
|
54
|
+
it "should be nil for a state that has not specified a fails_to" do
|
55
|
+
expect(flow_map.current_state.redirects_to).to be_nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return the redirects_to state if a redirects_to was specified" do
|
59
|
+
flow_map.init(flow: :new_todo, state: :deprecated)
|
60
|
+
expect(flow_map.current_state.redirects_to).to be_a(Stealth::Session)
|
61
|
+
expect(flow_map.current_state.redirects_to.state_string).to eq 'new'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return the redirects_to state if a redirects_to was specified as a session" do
|
65
|
+
flow_map.init(flow: :new_todo, state: :deprecated2)
|
66
|
+
expect(flow_map.current_state.redirects_to).to be_a(Stealth::Session)
|
67
|
+
expect(flow_map.current_state.redirects_to.state_string).to eq 'say_hi'
|
68
|
+
expect(flow_map.current_state.redirects_to.flow_string).to eq 'other_flow'
|
40
69
|
end
|
41
70
|
end
|
42
71
|
|
@@ -49,7 +78,7 @@ describe Stealth::Flow::State do
|
|
49
78
|
|
50
79
|
it "should decrement the state" do
|
51
80
|
flow_map.init(flow: :new_todo, state: :error)
|
52
|
-
new_state = flow_map.current_state -
|
81
|
+
new_state = flow_map.current_state - 5.states
|
53
82
|
expect(new_state).to eq(:get_due_date)
|
54
83
|
end
|
55
84
|
|
@@ -61,7 +90,7 @@ describe Stealth::Flow::State do
|
|
61
90
|
|
62
91
|
it "should return the last state if the increment is out of bounds" do
|
63
92
|
flow_map.init(flow: :new_todo, state: :created)
|
64
|
-
new_state = flow_map.current_state +
|
93
|
+
new_state = flow_map.current_state + 10.states
|
65
94
|
expect(new_state).to eq(:error)
|
66
95
|
end
|
67
96
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
- reply_type: delay # position 0
|
2
|
+
duration: dynamic
|
3
|
+
- reply_type: text
|
4
|
+
text: "Lorem ipsum dolor sit amet posuere."
|
5
|
+
- reply_type: delay # position 2
|
6
|
+
duration: dynamic
|
7
|
+
- reply_type: text
|
8
|
+
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin in lobortis ante. Duis elementum lacus sit amet volutpat."
|
9
|
+
- reply_type: delay # position 4
|
10
|
+
duration: dynamic
|
11
|
+
- reply_type: text
|
12
|
+
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer quis fermentum arcu, eget maximus metus. Vivamus ante tortor, scelerisque vel laoreet sit amet, sodales in augue. Nam vel quam a tellus mattis vestibulum non a amet."
|
13
|
+
buttons:
|
14
|
+
- text: "Cool"
|
15
|
+
payload: cool
|
16
|
+
- text: "Show me more"
|
17
|
+
payload: more
|
18
|
+
- reply_type: delay # position 6
|
19
|
+
duration: dynamic
|
20
|
+
- reply_type: text
|
21
|
+
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis consequat dolor. Suspendisse sed egestas lacus. Nam a viverra risus. Aliquam erat volutpat. Nunc molestie, metus ut cursus varius, purus quam pharetra nisi, sit amet porttitor tellus nisl sit amet est. Nam volutpat id lorem a condimentum. Sed quam mauris, faucibus sed pharetra sed."
|
22
|
+
- reply_type: delay # position 8
|
23
|
+
duration: dynamic
|
24
|
+
- reply_type: image
|
25
|
+
text: "https://via.placeholder.com/350x150"
|
26
|
+
- reply_type: delay # position 10
|
27
|
+
duration: dynamic
|
28
|
+
- reply_type: video
|
29
|
+
text: "https://via.placeholder.com/350x150"
|
30
|
+
- reply_type: delay # position 12
|
31
|
+
duration: dynamic
|
32
|
+
- reply_type: audio
|
33
|
+
text: "https://via.placeholder.com/350x150"
|
34
|
+
- reply_type: delay # position 14
|
35
|
+
duration: dynamic
|
36
|
+
- reply_type: file
|
37
|
+
text: "https://via.placeholder.com/350x150"
|
38
|
+
- reply_type: delay # position 16
|
39
|
+
duration: dynamic
|
40
|
+
- reply_type: cards
|
41
|
+
sharable: true
|
42
|
+
aspect_ratio: horizontal
|
43
|
+
elements:
|
44
|
+
- title: My App
|
45
|
+
subtitle: Download our app below or visit our website for more info.
|
46
|
+
image_url: "https://my-app.com/app-image.png"
|
47
|
+
buttons:
|
48
|
+
- type: url
|
49
|
+
url: "https://my-app.com"
|
50
|
+
text: 'View'
|
51
|
+
webview_height: 'tall'
|
52
|
+
- type: url
|
53
|
+
url: "https://itunes.apple.com/us/app/my-app"
|
54
|
+
text: 'Download iOS App'
|
55
|
+
- reply_type: delay # position 18
|
56
|
+
duration: dynamic
|
57
|
+
- reply_type: list
|
58
|
+
top_element_style: large
|
59
|
+
buttons:
|
60
|
+
- type: payload
|
61
|
+
text: View More
|
62
|
+
payload: view_more
|
63
|
+
elements:
|
64
|
+
- title: Your Daily News Update
|
65
|
+
subtitle: The following stories have been curated just for you.
|
66
|
+
image_url: "https://loremflickr.com/320/240"
|
67
|
+
buttons:
|
68
|
+
- type: url
|
69
|
+
url: "https://news-articles.com/199"
|
70
|
+
text: 'View'
|
71
|
+
webview_height: 'tall'
|
72
|
+
- title: Breakthrough in AI
|
73
|
+
subtitle: Major breakthrough in the AI space.
|
74
|
+
image_url: "https://loremflickr.com/320/320"
|
75
|
+
default_action:
|
76
|
+
- url: "https://news-articles.com/232"
|
77
|
+
webview_height: 'tall'
|
78
|
+
- reply_type: delay # position 20
|
79
|
+
duration: dynamic
|
data/spec/session_spec.rb
CHANGED
@@ -107,4 +107,21 @@ describe "Stealth::Session" do
|
|
107
107
|
expect(new_session.state_string).to eq('error')
|
108
108
|
end
|
109
109
|
end
|
110
|
+
|
111
|
+
describe "self.is_a_session_string?" do
|
112
|
+
it "should return false for state strings" do
|
113
|
+
session_string = 'say_hello'
|
114
|
+
expect(Stealth::Session.is_a_session_string?(session_string)).to be false
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should return false for an incomplete session string" do
|
118
|
+
session_string = 'hello->'
|
119
|
+
expect(Stealth::Session.is_a_session_string?(session_string)).to be false
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should return true for a complete session string" do
|
123
|
+
session_string = 'hello->say_hello'
|
124
|
+
expect(Stealth::Session.is_a_session_string?(session_string)).to be true
|
125
|
+
end
|
126
|
+
end
|
110
127
|
end
|