twilio-ruby 5.6.4 → 5.7.0
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 +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGES.md +9 -0
- data/Gemfile +1 -0
- data/README.md +2 -2
- data/lib/twilio-ruby/jwt/client_capability.rb +1 -1
- data/lib/twilio-ruby/rest/studio/v1/flow/engagement.rb +16 -7
- data/lib/twilio-ruby/rest/studio/v1/flow/engagement/engagement_context.rb +215 -0
- data/lib/twilio-ruby/rest/studio/v1/flow/engagement/step.rb +25 -7
- data/lib/twilio-ruby/rest/studio/v1/flow/engagement/step/step_context.rb +230 -0
- data/lib/twilio-ruby/twiml/twiml.rb +7 -4
- data/lib/twilio-ruby/version.rb +1 -1
- data/spec/integration/studio/v1/flow/engagement/engagement_context_spec.rb +49 -0
- data/spec/integration/studio/v1/flow/engagement/step/step_context_spec.rb +52 -0
- data/spec/integration/studio/v1/flow/engagement/step_spec.rb +4 -2
- data/spec/integration/studio/v1/flow/engagement_spec.rb +4 -8
- data/spec/spec_helper.rb +6 -0
- data/spec/twiml/messaging_response_spec.rb +137 -46
- data/spec/twiml/voice_response_spec.rb +554 -257
- metadata +8 -2
|
@@ -34,11 +34,14 @@ module Twilio
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def to_s(xml_declaration = true)
|
|
37
|
-
|
|
37
|
+
save_opts = Nokogiri::XML::Node::SaveOptions::DEFAULT_XML
|
|
38
|
+
if !xml_declaration
|
|
39
|
+
save_opts = save_opts | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
|
40
|
+
end
|
|
41
|
+
opts = { encoding: 'UTF-8', indent: 0, save_with: save_opts }
|
|
38
42
|
document = Nokogiri::XML::Document.new
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
xml
|
|
43
|
+
document << self.xml(document)
|
|
44
|
+
document.to_xml(opts)
|
|
42
45
|
end
|
|
43
46
|
|
|
44
47
|
def xml(document)
|
data/lib/twilio-ruby/version.rb
CHANGED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
##
|
|
2
|
+
# This code was generated by
|
|
3
|
+
# \ / _ _ _| _ _
|
|
4
|
+
# | (_)\/(_)(_|\/| |(/_ v1.0.0
|
|
5
|
+
# / /
|
|
6
|
+
|
|
7
|
+
require 'spec_helper.rb'
|
|
8
|
+
|
|
9
|
+
describe 'EngagementContext' do
|
|
10
|
+
it "can fetch" do
|
|
11
|
+
@holodeck.mock(Twilio::Response.new(500, ''))
|
|
12
|
+
|
|
13
|
+
expect {
|
|
14
|
+
@client.studio.v1.flows('FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
15
|
+
.engagements('FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
16
|
+
.engagement_context().fetch()
|
|
17
|
+
}.to raise_exception(Twilio::REST::TwilioError)
|
|
18
|
+
|
|
19
|
+
values = {}
|
|
20
|
+
expect(
|
|
21
|
+
@holodeck.has_request?(Holodeck::Request.new(
|
|
22
|
+
method: 'get',
|
|
23
|
+
url: 'https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Context',
|
|
24
|
+
))).to eq(true)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "receives fetch responses" do
|
|
28
|
+
@holodeck.mock(Twilio::Response.new(
|
|
29
|
+
200,
|
|
30
|
+
%q[
|
|
31
|
+
{
|
|
32
|
+
"account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
33
|
+
"context": {
|
|
34
|
+
"foo": "bar"
|
|
35
|
+
},
|
|
36
|
+
"flow_sid": "FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
37
|
+
"engagement_sid": "FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
38
|
+
"url": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Context"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
))
|
|
42
|
+
|
|
43
|
+
actual = @client.studio.v1.flows('FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
44
|
+
.engagements('FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
45
|
+
.engagement_context().fetch()
|
|
46
|
+
|
|
47
|
+
expect(actual).to_not eq(nil)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
##
|
|
2
|
+
# This code was generated by
|
|
3
|
+
# \ / _ _ _| _ _
|
|
4
|
+
# | (_)\/(_)(_|\/| |(/_ v1.0.0
|
|
5
|
+
# / /
|
|
6
|
+
|
|
7
|
+
require 'spec_helper.rb'
|
|
8
|
+
|
|
9
|
+
describe 'StepContext' do
|
|
10
|
+
it "can fetch" do
|
|
11
|
+
@holodeck.mock(Twilio::Response.new(500, ''))
|
|
12
|
+
|
|
13
|
+
expect {
|
|
14
|
+
@client.studio.v1.flows('FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
15
|
+
.engagements('FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
16
|
+
.steps('FTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
17
|
+
.step_context().fetch()
|
|
18
|
+
}.to raise_exception(Twilio::REST::TwilioError)
|
|
19
|
+
|
|
20
|
+
values = {}
|
|
21
|
+
expect(
|
|
22
|
+
@holodeck.has_request?(Holodeck::Request.new(
|
|
23
|
+
method: 'get',
|
|
24
|
+
url: 'https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Steps/FTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Context',
|
|
25
|
+
))).to eq(true)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "receives fetch responses" do
|
|
29
|
+
@holodeck.mock(Twilio::Response.new(
|
|
30
|
+
200,
|
|
31
|
+
%q[
|
|
32
|
+
{
|
|
33
|
+
"account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
34
|
+
"context": {
|
|
35
|
+
"foo": "bar"
|
|
36
|
+
},
|
|
37
|
+
"flow_sid": "FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
38
|
+
"engagement_sid": "FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
39
|
+
"step_sid": "FTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
40
|
+
"url": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Steps/FTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Context"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
))
|
|
44
|
+
|
|
45
|
+
actual = @client.studio.v1.flows('FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
46
|
+
.engagements('FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
47
|
+
.steps('FTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') \
|
|
48
|
+
.step_context().fetch()
|
|
49
|
+
|
|
50
|
+
expect(actual).to_not eq(nil)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -77,12 +77,14 @@ describe 'Step' do
|
|
|
77
77
|
"flow_sid": "FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
78
78
|
"engagement_sid": "FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
79
79
|
"name": "incomingRequest",
|
|
80
|
-
"context": {},
|
|
81
80
|
"transitioned_from": "Trigger",
|
|
82
81
|
"transitioned_to": "Ended",
|
|
83
82
|
"date_created": "2017-11-06T12:00:00Z",
|
|
84
83
|
"date_updated": null,
|
|
85
|
-
"url": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Steps/FTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
84
|
+
"url": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Steps/FTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
85
|
+
"links": {
|
|
86
|
+
"step_context": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Steps/FTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Context"
|
|
87
|
+
}
|
|
86
88
|
}
|
|
87
89
|
]
|
|
88
90
|
))
|
|
@@ -75,12 +75,12 @@ describe 'Engagement' do
|
|
|
75
75
|
"contact_sid": "FCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
76
76
|
"contact_channel_address": "+14155555555",
|
|
77
77
|
"status": "ended",
|
|
78
|
-
"context": {},
|
|
79
78
|
"date_created": "2017-11-06T12:00:00Z",
|
|
80
79
|
"date_updated": null,
|
|
81
80
|
"url": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
82
81
|
"links": {
|
|
83
|
-
"steps": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Steps"
|
|
82
|
+
"steps": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Steps",
|
|
83
|
+
"engagement_context": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Context"
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
]
|
|
@@ -118,18 +118,14 @@ describe 'Engagement' do
|
|
|
118
118
|
"sid": "FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
119
119
|
"account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
120
120
|
"flow_sid": "FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
121
|
-
"context": {
|
|
122
|
-
"flow": {
|
|
123
|
-
"first_name": "Foo"
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
121
|
"contact_sid": "FCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
127
122
|
"contact_channel_address": "+18001234567",
|
|
128
123
|
"status": "active",
|
|
129
124
|
"date_created": "2015-07-30T20:00:00Z",
|
|
130
125
|
"date_updated": "2015-07-30T20:00:00Z",
|
|
131
126
|
"links": {
|
|
132
|
-
"steps": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Steps"
|
|
127
|
+
"steps": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Steps",
|
|
128
|
+
"engagement_context": "https://studio.twilio.com/v1/Flows/FWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Engagements/FNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Context"
|
|
133
129
|
}
|
|
134
130
|
}
|
|
135
131
|
]
|
data/spec/spec_helper.rb
CHANGED
|
@@ -10,6 +10,8 @@ require_relative './holodeck/hologram.rb'
|
|
|
10
10
|
|
|
11
11
|
require 'twilio-ruby'
|
|
12
12
|
require 'rack'
|
|
13
|
+
require 'rspec/matchers'
|
|
14
|
+
require 'equivalent-xml'
|
|
13
15
|
|
|
14
16
|
RSpec.configure do |config|
|
|
15
17
|
config.expect_with :rspec do |c|
|
|
@@ -30,3 +32,7 @@ end
|
|
|
30
32
|
def auth_token
|
|
31
33
|
ENV['AUTH_TOKEN']
|
|
32
34
|
end
|
|
35
|
+
|
|
36
|
+
def parse(twiml_response)
|
|
37
|
+
Nokogiri::XML::Document.parse(twiml_response.to_s, &:noblanks)
|
|
38
|
+
end
|
|
@@ -3,93 +3,184 @@ require 'spec_helper'
|
|
|
3
3
|
describe Twilio::TwiML::MessagingResponse do
|
|
4
4
|
context 'Testing Response' do
|
|
5
5
|
it 'should allow empty response' do
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
expected_doc = parse <<-XML
|
|
7
|
+
<Response/>
|
|
8
|
+
XML
|
|
9
|
+
response = Twilio::TwiML::MessagingResponse.new.to_s
|
|
10
|
+
doc = parse(response)
|
|
11
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
8
12
|
end
|
|
9
13
|
|
|
10
14
|
it 'should allow using to_xml instead of to_s' do
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
expected_doc = parse <<-XML
|
|
16
|
+
<Response/>
|
|
17
|
+
XML
|
|
18
|
+
response = Twilio::TwiML::MessagingResponse.new.to_xml
|
|
19
|
+
doc = parse(response)
|
|
20
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
13
21
|
end
|
|
14
22
|
|
|
15
23
|
it 'should allow populated response' do
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
expected_doc = parse <<-XML
|
|
25
|
+
<Response>
|
|
26
|
+
<Message>Hello</Message>
|
|
27
|
+
<Redirect>example.com</Redirect>
|
|
28
|
+
</Response>
|
|
29
|
+
XML
|
|
30
|
+
response = Twilio::TwiML::MessagingResponse.new
|
|
31
|
+
response.message(body: 'Hello')
|
|
32
|
+
response.redirect('example.com')
|
|
33
|
+
doc = parse(response)
|
|
34
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
21
35
|
end
|
|
22
36
|
|
|
23
37
|
it 'should allow chaining' do
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
38
|
+
expected_doc = parse <<-XML
|
|
39
|
+
<Response>
|
|
40
|
+
<Message>Hello</Message>
|
|
41
|
+
<Redirect>example.com</Redirect>
|
|
42
|
+
</Response>
|
|
43
|
+
XML
|
|
44
|
+
response = Twilio::TwiML::MessagingResponse.new.message(body: 'Hello').redirect('example.com')
|
|
45
|
+
doc = parse(response)
|
|
46
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
27
47
|
end
|
|
28
48
|
|
|
29
49
|
it 'should allow nesting' do
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
50
|
+
expected_doc = parse <<-XML
|
|
51
|
+
<Response>
|
|
52
|
+
<Message>
|
|
53
|
+
Hello
|
|
54
|
+
<Media>foobar</Media>
|
|
55
|
+
</Message>
|
|
56
|
+
</Response>
|
|
57
|
+
XML
|
|
58
|
+
response = Twilio::TwiML::MessagingResponse.new
|
|
59
|
+
response.message(body: 'Hello') do |message|
|
|
60
|
+
message.media('foobar')
|
|
33
61
|
end
|
|
34
|
-
|
|
35
|
-
expect(
|
|
62
|
+
doc = parse(response)
|
|
63
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
36
64
|
end
|
|
37
65
|
|
|
38
66
|
it 'should allow nesting and chaining' do
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
67
|
+
expected_doc = parse <<-XML
|
|
68
|
+
<Response>
|
|
69
|
+
<Message>
|
|
70
|
+
Hello
|
|
71
|
+
<Media>foobar</Media>
|
|
72
|
+
</Message>
|
|
73
|
+
<Redirect>example.com</Redirec>
|
|
74
|
+
</Response>
|
|
75
|
+
XML
|
|
76
|
+
response = Twilio::TwiML::MessagingResponse.new
|
|
77
|
+
response.message(body: 'Hello') do |message|
|
|
78
|
+
message.media('foobar')
|
|
42
79
|
end
|
|
43
80
|
|
|
44
|
-
|
|
81
|
+
response.redirect('example.com')
|
|
45
82
|
|
|
46
|
-
|
|
83
|
+
doc = parse(response)
|
|
84
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
47
85
|
end
|
|
48
86
|
|
|
49
87
|
it 'should allow nesting from the initializer' do
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
88
|
+
expected_doc = parse <<-XML
|
|
89
|
+
<Response>
|
|
90
|
+
<Message>Hello</Message>
|
|
91
|
+
<Redirect>example.com</Redirec>
|
|
92
|
+
</Response>
|
|
93
|
+
XML
|
|
94
|
+
response = Twilio::TwiML::MessagingResponse.new do |res|
|
|
95
|
+
res.message(body: 'Hello')
|
|
96
|
+
res.redirect('example.com')
|
|
53
97
|
end
|
|
54
|
-
|
|
98
|
+
doc = parse(response)
|
|
99
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
55
100
|
end
|
|
56
101
|
end
|
|
57
102
|
|
|
58
103
|
context 'Testing Message' do
|
|
59
104
|
it 'should allow a body' do
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
105
|
+
expected_doc = parse <<-XML
|
|
106
|
+
<Response>
|
|
107
|
+
<Message>Hello</Message>
|
|
108
|
+
</Response>
|
|
109
|
+
XML
|
|
110
|
+
response = Twilio::TwiML::MessagingResponse.new
|
|
111
|
+
response.message(body: 'Hello')
|
|
112
|
+
doc = parse(response)
|
|
113
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
64
114
|
end
|
|
65
115
|
|
|
66
116
|
it 'should allow appending Body' do
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
117
|
+
expected_doc = parse <<-XML
|
|
118
|
+
<Response>
|
|
119
|
+
<Message><Body>Hello World</Body></Message>
|
|
120
|
+
</Response>
|
|
121
|
+
XML
|
|
122
|
+
body = Twilio::TwiML::Body.new('Hello World')
|
|
123
|
+
message = Twilio::TwiML::Message.new
|
|
124
|
+
|
|
125
|
+
response = Twilio::TwiML::MessagingResponse.new
|
|
126
|
+
message.append(body)
|
|
127
|
+
response.append(message)
|
|
128
|
+
|
|
129
|
+
doc = parse(response)
|
|
130
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
73
131
|
end
|
|
74
132
|
|
|
75
133
|
it 'should allow appending Body and Media' do
|
|
76
|
-
|
|
77
|
-
|
|
134
|
+
expected_doc = parse <<-XML
|
|
135
|
+
<Response>
|
|
136
|
+
<Message>
|
|
137
|
+
<Body>Hello World</Body>
|
|
138
|
+
<Media>hey.jpg</Media>
|
|
139
|
+
</Message>
|
|
140
|
+
</Response>
|
|
141
|
+
XML
|
|
142
|
+
body = Twilio::TwiML::Body.new('Hello World')
|
|
143
|
+
media = Twilio::TwiML::Media.new('hey.jpg')
|
|
144
|
+
message = Twilio::TwiML::Message.new
|
|
145
|
+
|
|
146
|
+
response = Twilio::TwiML::MessagingResponse.new
|
|
147
|
+
message.append(body)
|
|
148
|
+
message.append(media)
|
|
149
|
+
response.append(message)
|
|
150
|
+
|
|
151
|
+
doc = parse(response)
|
|
152
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
153
|
+
end
|
|
78
154
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
155
|
+
it 'should allow and preserve new lines in messages' do
|
|
156
|
+
expected_doc = parse <<-XML
|
|
157
|
+
<Response>
|
|
158
|
+
<Message>Hello
|
|
159
|
+
World
|
|
160
|
+
</Message>
|
|
161
|
+
</Response>
|
|
162
|
+
XML
|
|
82
163
|
|
|
83
|
-
|
|
164
|
+
response = Twilio::TwiML::MessagingResponse.new
|
|
165
|
+
response.message(body: "Hello\nWorld")
|
|
166
|
+
|
|
167
|
+
doc = parse(response)
|
|
168
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
84
169
|
end
|
|
85
170
|
end
|
|
86
171
|
|
|
87
172
|
context 'Testing Redirect' do
|
|
88
173
|
it 'should allow MessagingResponse.redirect' do
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
174
|
+
expected_doc = parse <<-XML
|
|
175
|
+
<Response>
|
|
176
|
+
<Redirect>example.com</Redirect>
|
|
177
|
+
</Response>
|
|
178
|
+
XML
|
|
179
|
+
response = Twilio::TwiML::MessagingResponse.new
|
|
180
|
+
response.redirect('example.com')
|
|
181
|
+
|
|
182
|
+
doc = parse(response)
|
|
183
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
93
184
|
end
|
|
94
185
|
end
|
|
95
186
|
end
|
|
@@ -3,252 +3,428 @@ require 'spec_helper'
|
|
|
3
3
|
describe Twilio::TwiML::VoiceResponse do
|
|
4
4
|
context 'Testing Response' do
|
|
5
5
|
it 'should allow empty response' do
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
expected_doc = parse <<-XML
|
|
7
|
+
<Response/>
|
|
8
|
+
XML
|
|
9
|
+
response = Twilio::TwiML::VoiceResponse.new.to_s
|
|
10
|
+
doc = parse(response)
|
|
11
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
8
12
|
end
|
|
9
13
|
|
|
10
14
|
it 'should allow using to_xml instead of to_s' do
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
expected_doc = parse <<-XML
|
|
16
|
+
<Response/>
|
|
17
|
+
XML
|
|
18
|
+
response = Twilio::TwiML::VoiceResponse.new.to_xml
|
|
19
|
+
doc = parse(response)
|
|
20
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
13
21
|
end
|
|
14
22
|
|
|
15
|
-
it 'should
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
r.sms('twilio sms', to: '+11234567890', from: '+10987654321')
|
|
23
|
+
it 'should have an xml declaration by default' do
|
|
24
|
+
twiml = Twilio::TwiML::VoiceResponse.new.to_xml
|
|
25
|
+
expect(twiml).to match(/\A<\?xml version="1.0" encoding="UTF-8"\?>/)
|
|
26
|
+
end
|
|
20
27
|
|
|
21
|
-
|
|
28
|
+
it 'should allow no xml_declaration' do
|
|
29
|
+
twiml = Twilio::TwiML::VoiceResponse.new.to_xml(false)
|
|
30
|
+
expect(twiml).not_to match(/\A<\?xml version="1.0" encoding="UTF-8"\?>/)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'should allow populated response' do
|
|
34
|
+
expected_doc = parse <<-XML
|
|
35
|
+
<Response>
|
|
36
|
+
<Hangup/>
|
|
37
|
+
<Leave/>
|
|
38
|
+
<Sms to="+11234567890" from="+10987654321">twilio sms</Sms>
|
|
39
|
+
</Response>
|
|
40
|
+
XML
|
|
41
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
42
|
+
response.hangup
|
|
43
|
+
response.leave
|
|
44
|
+
response.sms('twilio sms', to: '+11234567890', from: '+10987654321')
|
|
45
|
+
|
|
46
|
+
doc = parse(response)
|
|
47
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
22
48
|
end
|
|
23
49
|
|
|
24
50
|
it 'should allow chaining' do
|
|
25
|
-
|
|
51
|
+
expected_doc = parse <<-XML
|
|
52
|
+
<Response>
|
|
53
|
+
<Hangup/>
|
|
54
|
+
<Leave/>
|
|
55
|
+
<Sms to="+11234567890" from="+10987654321">twilio sms</Sms>
|
|
56
|
+
</Response>
|
|
57
|
+
XML
|
|
58
|
+
response = Twilio::TwiML::VoiceResponse.new.hangup.leave.sms(
|
|
26
59
|
'twilio sms',
|
|
27
60
|
to: '+11234567890',
|
|
28
61
|
from: '+10987654321'
|
|
29
62
|
)
|
|
30
63
|
|
|
31
|
-
|
|
64
|
+
doc = parse(response)
|
|
65
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
32
66
|
end
|
|
33
67
|
|
|
34
68
|
it 'should allow nesting' do
|
|
69
|
+
expected_doc = parse <<-XML
|
|
70
|
+
<Response>
|
|
71
|
+
<Hangup/>
|
|
72
|
+
<Leave/>
|
|
73
|
+
<Sms to="+11234567890" from="+10987654321">twilio sms</Sms>
|
|
74
|
+
</Response>
|
|
75
|
+
XML
|
|
35
76
|
response = Twilio::TwiML::VoiceResponse.new do |r|
|
|
36
77
|
r.hangup
|
|
37
78
|
r.leave
|
|
38
79
|
r.sms('twilio sms', to: '+11234567890', from: '+10987654321')
|
|
39
80
|
end
|
|
40
|
-
|
|
81
|
+
|
|
82
|
+
doc = parse(response)
|
|
83
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
41
84
|
end
|
|
42
85
|
end
|
|
43
86
|
|
|
44
87
|
context 'Testing Say' do
|
|
45
88
|
it 'should allow empty say' do
|
|
46
|
-
|
|
47
|
-
|
|
89
|
+
expected_doc = parse <<-XML
|
|
90
|
+
<Response>
|
|
91
|
+
<Say></Say>
|
|
92
|
+
</Response>
|
|
93
|
+
XML
|
|
94
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
95
|
+
response.say ''
|
|
48
96
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
expect(r.to_s)
|
|
52
|
-
.to eq('<?xml version="1.0" encoding="UTF-8"?><Response><Say></Say></Response>')
|
|
53
|
-
.or(eq('<?xml version="1.0" encoding="UTF-8"?><Response><Say/></Response>'))
|
|
97
|
+
doc = parse(response)
|
|
98
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
54
99
|
end
|
|
55
100
|
|
|
56
101
|
it 'should allow populated say' do
|
|
57
|
-
|
|
58
|
-
|
|
102
|
+
expected_doc = parse <<-XML
|
|
103
|
+
<Response>
|
|
104
|
+
<Say>Hello World</Say>
|
|
105
|
+
</Response>
|
|
106
|
+
XML
|
|
107
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
108
|
+
response.say 'Hello World'
|
|
59
109
|
|
|
60
|
-
|
|
110
|
+
doc = parse(response)
|
|
111
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
61
112
|
end
|
|
62
113
|
|
|
63
114
|
it 'should allow unicode say' do
|
|
64
|
-
|
|
65
|
-
|
|
115
|
+
expected_doc = parse <<-XML
|
|
116
|
+
<Response>
|
|
117
|
+
<Say>nécessaire et d'autres</Say>
|
|
118
|
+
</Response>
|
|
119
|
+
XML
|
|
120
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
121
|
+
response.say 'nécessaire et d\'autres'
|
|
66
122
|
|
|
67
|
-
|
|
123
|
+
doc = parse(response)
|
|
124
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
68
125
|
end
|
|
69
126
|
|
|
70
127
|
it 'should allow looping' do
|
|
71
|
-
|
|
72
|
-
|
|
128
|
+
expected_doc = parse <<-XML
|
|
129
|
+
<Response>
|
|
130
|
+
<Say loop="3">Hello Monkey</Say>
|
|
131
|
+
</Response>
|
|
132
|
+
XML
|
|
133
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
134
|
+
response.say 'Hello Monkey', loop: 3
|
|
73
135
|
|
|
74
|
-
|
|
136
|
+
doc = parse(response)
|
|
137
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
75
138
|
end
|
|
76
139
|
|
|
77
140
|
it 'should allow languages' do
|
|
78
|
-
|
|
79
|
-
|
|
141
|
+
expected_doc = parse <<-XML
|
|
142
|
+
<Response>
|
|
143
|
+
<Say language="en-gb">Hello Monkey</Say>
|
|
144
|
+
</Response>
|
|
145
|
+
XML
|
|
146
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
147
|
+
response.say 'Hello Monkey', language: 'en-gb'
|
|
80
148
|
|
|
81
|
-
|
|
149
|
+
doc = parse(response)
|
|
150
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
82
151
|
end
|
|
83
152
|
|
|
84
153
|
it 'should allow all attributes' do
|
|
85
|
-
|
|
86
|
-
|
|
154
|
+
expected_doc = parse <<-XML
|
|
155
|
+
<Response>
|
|
156
|
+
<Say loop="3" voice="man" language="fr">Hello Monkey</Say>
|
|
157
|
+
</Response>
|
|
158
|
+
XML
|
|
159
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
160
|
+
response.say 'Hello Monkey', loop: 3, voice: 'man', language: 'fr'
|
|
87
161
|
|
|
88
|
-
|
|
162
|
+
doc = parse(response)
|
|
163
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
89
164
|
end
|
|
90
165
|
end
|
|
91
166
|
|
|
92
167
|
context 'Testing Play' do
|
|
93
168
|
it 'should allow empty play' do
|
|
94
|
-
|
|
95
|
-
|
|
169
|
+
expected_doc = parse <<-XML
|
|
170
|
+
<Response>
|
|
171
|
+
<Play></Play>
|
|
172
|
+
</Response>
|
|
173
|
+
XML
|
|
174
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
175
|
+
response.play
|
|
96
176
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
expect(r.to_s)
|
|
100
|
-
.to eq('<?xml version="1.0" encoding="UTF-8"?><Response><Play></Play></Response>')
|
|
101
|
-
.or(eq('<?xml version="1.0" encoding="UTF-8"?><Response><Play/></Response>'))
|
|
177
|
+
doc = parse(response)
|
|
178
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
102
179
|
end
|
|
103
180
|
|
|
104
181
|
it 'should play hello' do
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
182
|
+
expected_doc = parse <<-XML
|
|
183
|
+
<Response>
|
|
184
|
+
<Play>http://hellomonkey.mp3</Play>
|
|
185
|
+
</Response>
|
|
186
|
+
XML
|
|
187
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
188
|
+
response.play(url: 'http://hellomonkey.mp3')
|
|
189
|
+
doc = parse(response)
|
|
190
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
109
191
|
end
|
|
110
192
|
|
|
111
193
|
it 'should play hello on loop' do
|
|
112
|
-
|
|
113
|
-
|
|
194
|
+
expected_doc = parse <<-XML
|
|
195
|
+
<Response>
|
|
196
|
+
<Play loop="3">http://hellomonkey.mp3</Play>
|
|
197
|
+
</Response>
|
|
198
|
+
XML
|
|
199
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
200
|
+
response.play(url: 'http://hellomonkey.mp3', loop: 3)
|
|
114
201
|
|
|
115
|
-
|
|
202
|
+
doc = parse(response)
|
|
203
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
116
204
|
end
|
|
117
205
|
|
|
118
206
|
it 'should play digits' do
|
|
119
|
-
|
|
120
|
-
|
|
207
|
+
expected_doc = parse <<-XML
|
|
208
|
+
<Response>
|
|
209
|
+
<Play digits="w123"></Play>
|
|
210
|
+
</Response>
|
|
211
|
+
XML
|
|
212
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
213
|
+
response.play(digits: 'w123')
|
|
121
214
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
expect(r.to_s)
|
|
125
|
-
.to eq('<?xml version="1.0" encoding="UTF-8"?><Response><Play digits="w123"></Play></Response>')
|
|
126
|
-
.or(eq('<?xml version="1.0" encoding="UTF-8"?><Response><Play digits="w123"/></Response>'))
|
|
215
|
+
doc = parse(response)
|
|
216
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
127
217
|
end
|
|
128
218
|
end
|
|
129
219
|
|
|
130
220
|
context 'Testing Record' do
|
|
131
221
|
it 'should allow empty record' do
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
222
|
+
expected_doc = parse <<-XML
|
|
223
|
+
<Response>
|
|
224
|
+
<Record/>
|
|
225
|
+
</Response>
|
|
226
|
+
XML
|
|
227
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
228
|
+
response.record
|
|
229
|
+
doc = parse(response)
|
|
230
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
136
231
|
end
|
|
137
232
|
|
|
138
233
|
it 'should allow action and method' do
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
234
|
+
expected_doc = parse <<-XML
|
|
235
|
+
<Response>
|
|
236
|
+
<Record action="example.com" method="GET" />
|
|
237
|
+
</Response>
|
|
238
|
+
XML
|
|
239
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
240
|
+
response.record(action: 'example.com', method: 'GET')
|
|
241
|
+
doc = parse(response)
|
|
242
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
143
243
|
end
|
|
144
244
|
|
|
145
245
|
it 'should allow max_length, finish_on_key, and timeout' do
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
246
|
+
expected_doc = parse <<-XML
|
|
247
|
+
<Response>
|
|
248
|
+
<Record timeout="4" finishOnKey="#" maxLength="30" />
|
|
249
|
+
</Response>
|
|
250
|
+
XML
|
|
251
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
252
|
+
response.record(timeout: 4, finish_on_key: '#', max_length: 30)
|
|
253
|
+
doc = parse(response)
|
|
254
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
150
255
|
end
|
|
151
256
|
|
|
152
257
|
it 'should allow transcribe' do
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
258
|
+
expected_doc = parse <<-XML
|
|
259
|
+
<Response>
|
|
260
|
+
<Record transcribeCallback="example.com" />
|
|
261
|
+
</Response>
|
|
262
|
+
XML
|
|
263
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
264
|
+
response.record(transcribe_callback: 'example.com')
|
|
265
|
+
doc = parse(response)
|
|
266
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
157
267
|
end
|
|
158
268
|
end
|
|
159
269
|
|
|
160
270
|
context 'Testing Redirect' do
|
|
161
271
|
it 'should allow empty redirect' do
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
272
|
+
expected_doc = parse <<-XML
|
|
273
|
+
<Response>
|
|
274
|
+
<Redirect/>
|
|
275
|
+
</Response>
|
|
276
|
+
XML
|
|
277
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
278
|
+
response.redirect ''
|
|
279
|
+
doc = parse(response)
|
|
280
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
170
281
|
end
|
|
171
282
|
|
|
172
283
|
it 'should allow method' do
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
284
|
+
expected_doc = parse <<-XML
|
|
285
|
+
<Response>
|
|
286
|
+
<Redirect method="POST">example.com</Redirect>
|
|
287
|
+
</Response>
|
|
288
|
+
XML
|
|
289
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
290
|
+
response.redirect('example.com', method: 'POST')
|
|
291
|
+
doc = parse(response)
|
|
292
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
177
293
|
end
|
|
178
294
|
|
|
179
295
|
it 'should allow method and params' do
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
296
|
+
expected_doc = parse <<-XML
|
|
297
|
+
<Response>
|
|
298
|
+
<Redirect method="POST">example.com?id=34&action=hey</Redirect>
|
|
299
|
+
</Response>
|
|
300
|
+
XML
|
|
301
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
302
|
+
response.redirect('example.com?id=34&action=hey', method: 'POST')
|
|
303
|
+
doc = parse(response)
|
|
304
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
184
305
|
end
|
|
185
306
|
end
|
|
186
307
|
|
|
187
308
|
context 'Testing Hangup' do
|
|
188
309
|
it 'should allow hangup' do
|
|
189
|
-
|
|
190
|
-
|
|
310
|
+
expected_doc = parse <<-XML
|
|
311
|
+
<Response>
|
|
312
|
+
<Hangup/>
|
|
313
|
+
</Response>
|
|
314
|
+
XML
|
|
315
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
316
|
+
response.hangup
|
|
317
|
+
doc = parse(response)
|
|
318
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
319
|
+
end
|
|
191
320
|
|
|
192
|
-
|
|
321
|
+
it 'should not allow content in the hangup' do
|
|
322
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
323
|
+
expect { response.hangup 'Goodbye' }.to raise_error(ArgumentError)
|
|
193
324
|
end
|
|
194
325
|
end
|
|
195
326
|
|
|
196
327
|
context 'Testing Leave' do
|
|
197
328
|
it 'should allow leave' do
|
|
198
|
-
|
|
199
|
-
|
|
329
|
+
expected_doc = parse <<-XML
|
|
330
|
+
<Response>
|
|
331
|
+
<Leave/>
|
|
332
|
+
</Response>
|
|
333
|
+
XML
|
|
334
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
335
|
+
response.leave
|
|
336
|
+
doc = parse(response)
|
|
337
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
338
|
+
end
|
|
200
339
|
|
|
201
|
-
|
|
340
|
+
it 'should not allow content in the leave' do
|
|
341
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
342
|
+
expect { response.leave 'Goodbye' }.to raise_error(ArgumentError)
|
|
202
343
|
end
|
|
203
344
|
end
|
|
204
345
|
|
|
205
346
|
context 'Testing Reject' do
|
|
206
347
|
it 'should reject with a default reason' do
|
|
207
|
-
|
|
208
|
-
|
|
348
|
+
expected_doc = parse <<-XML
|
|
349
|
+
<Response>
|
|
350
|
+
<Reject/>
|
|
351
|
+
</Response>
|
|
352
|
+
XML
|
|
353
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
354
|
+
response.reject
|
|
355
|
+
doc = parse(response)
|
|
356
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
357
|
+
end
|
|
209
358
|
|
|
210
|
-
|
|
359
|
+
it 'should not allow content in the reject' do
|
|
360
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
361
|
+
expect { response.reject 'Goodbye' }.to raise_error(ArgumentError)
|
|
211
362
|
end
|
|
212
363
|
end
|
|
213
364
|
|
|
214
365
|
context 'Testing SMS' do
|
|
215
366
|
it 'should allow empty SMS' do
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
367
|
+
expected_doc = parse <<-XML
|
|
368
|
+
<Response>
|
|
369
|
+
<Sms/>
|
|
370
|
+
</Response>
|
|
371
|
+
XML
|
|
372
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
373
|
+
response.sms ''
|
|
374
|
+
doc = parse(response)
|
|
375
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
224
376
|
end
|
|
225
377
|
|
|
226
378
|
it 'should allow SMS body' do
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
379
|
+
expected_doc = parse <<-XML
|
|
380
|
+
<Response>
|
|
381
|
+
<Sms>Hello, World</Sms>
|
|
382
|
+
</Response>
|
|
383
|
+
XML
|
|
384
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
385
|
+
response.sms 'Hello, World'
|
|
386
|
+
doc = parse(response)
|
|
387
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
231
388
|
end
|
|
232
389
|
|
|
233
390
|
it 'should allow to, from, action, and status_callback' do
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
391
|
+
expected_doc = parse <<-XML
|
|
392
|
+
<Response>
|
|
393
|
+
<Sms to="1231231234" from="3453453456" statusCallback="example.com?id=34&action=hey">Hello, World</Sms>
|
|
394
|
+
</Response>
|
|
395
|
+
XML
|
|
396
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
397
|
+
response.sms('Hello, World', to: 1_231_231_234, from: 3_453_453_456, status_callback: 'example.com?id=34&action=hey')
|
|
398
|
+
doc = parse(response)
|
|
399
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
238
400
|
end
|
|
239
401
|
|
|
240
402
|
it 'should allow action and method' do
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
403
|
+
expected_doc = parse <<-XML
|
|
404
|
+
<Response>
|
|
405
|
+
<Sms method="POST" action="example.com?id=34&action=hey">Hello</Sms>
|
|
406
|
+
</Response>
|
|
407
|
+
XML
|
|
408
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
409
|
+
response.sms('Hello', method: 'POST', action: 'example.com?id=34&action=hey')
|
|
410
|
+
doc = parse(response)
|
|
411
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
245
412
|
end
|
|
246
413
|
end
|
|
247
414
|
|
|
248
415
|
context 'Testing Conference' do
|
|
249
416
|
it 'should allow basic conferencing' do
|
|
250
|
-
|
|
251
|
-
|
|
417
|
+
expected_doc = parse <<-XML
|
|
418
|
+
<Response>
|
|
419
|
+
<Dial>
|
|
420
|
+
<Conference beep="false" waitUrl="" startConferenceOnEnter="true" endConferenceOnExit="true">
|
|
421
|
+
TestConferenceAttributes
|
|
422
|
+
</Conference>
|
|
423
|
+
</Dial>
|
|
424
|
+
</Response>
|
|
425
|
+
XML
|
|
426
|
+
dial = Twilio::TwiML::Dial.new
|
|
427
|
+
dial.conference(
|
|
252
428
|
'TestConferenceAttributes',
|
|
253
429
|
beep: false,
|
|
254
430
|
wait_url: '',
|
|
@@ -256,15 +432,24 @@ describe Twilio::TwiML::VoiceResponse do
|
|
|
256
432
|
end_conference_on_exit: true
|
|
257
433
|
)
|
|
258
434
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
expect(
|
|
435
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
436
|
+
response.append(dial)
|
|
437
|
+
doc = parse(response)
|
|
438
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
263
439
|
end
|
|
264
440
|
|
|
265
441
|
it 'should allow muted conferencing' do
|
|
266
|
-
|
|
267
|
-
|
|
442
|
+
expected_doc = parse <<-XML
|
|
443
|
+
<Response>
|
|
444
|
+
<Dial>
|
|
445
|
+
<Conference beep="false" waitUrl="" startConferenceOnEnter="true" endConferenceOnExit="true" muted="true">
|
|
446
|
+
TestConferenceMutedAttribute
|
|
447
|
+
</Conference>
|
|
448
|
+
</Dial>
|
|
449
|
+
</Response>
|
|
450
|
+
XML
|
|
451
|
+
dial = Twilio::TwiML::Dial.new
|
|
452
|
+
dial.conference(
|
|
268
453
|
'TestConferenceMutedAttribute',
|
|
269
454
|
beep: false,
|
|
270
455
|
muted: true,
|
|
@@ -273,207 +458,319 @@ describe Twilio::TwiML::VoiceResponse do
|
|
|
273
458
|
end_conference_on_exit: true
|
|
274
459
|
)
|
|
275
460
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
expect(
|
|
461
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
462
|
+
response.append(dial)
|
|
463
|
+
doc = parse(response)
|
|
464
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
280
465
|
end
|
|
281
466
|
end
|
|
282
467
|
|
|
283
468
|
context 'Testing Queue' do
|
|
284
469
|
it 'should allow queues in VoiceResponse' do
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
470
|
+
expected_doc = parse <<-XML
|
|
471
|
+
<Response>
|
|
472
|
+
<Dial>
|
|
473
|
+
<Queue url="" method="GET">TestQueueAttribute</Queue>
|
|
474
|
+
</Dial>
|
|
475
|
+
</Response>
|
|
476
|
+
XML
|
|
477
|
+
dial = Twilio::TwiML::Dial.new
|
|
478
|
+
dial.queue('TestQueueAttribute', url: '', method: 'GET')
|
|
479
|
+
|
|
480
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
481
|
+
response.append(dial)
|
|
482
|
+
doc = parse(response)
|
|
483
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
292
484
|
end
|
|
293
485
|
end
|
|
294
486
|
|
|
295
487
|
context 'Testing Echo' do
|
|
296
488
|
it 'should allow VoiceResponse Echo' do
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
489
|
+
expected_doc = parse <<-XML
|
|
490
|
+
<Response>
|
|
491
|
+
<Echo/>
|
|
492
|
+
</Response>
|
|
493
|
+
XML
|
|
494
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
495
|
+
response.echo
|
|
496
|
+
doc = parse(response)
|
|
497
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
301
498
|
end
|
|
302
499
|
end
|
|
303
500
|
|
|
304
501
|
context 'Testing Enqueue' do
|
|
305
502
|
it 'should allow VoiceResponse.enqueue' do
|
|
306
|
-
|
|
307
|
-
|
|
503
|
+
expected_doc = parse <<-XML
|
|
504
|
+
<Response>
|
|
505
|
+
<Enqueue action="act" method="GET" waitUrl="wait" waitUrlMethod="POST">TestEnqueueAttribute</Enqueue>
|
|
506
|
+
</Response>
|
|
507
|
+
XML
|
|
508
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
509
|
+
response.enqueue(
|
|
308
510
|
name: 'TestEnqueueAttribute',
|
|
309
511
|
action: 'act',
|
|
310
512
|
method: 'GET',
|
|
311
513
|
wait_url: 'wait',
|
|
312
514
|
wait_url_method: 'POST'
|
|
313
515
|
)
|
|
314
|
-
|
|
315
|
-
expect(
|
|
516
|
+
doc = parse(response)
|
|
517
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
316
518
|
end
|
|
317
519
|
|
|
318
520
|
it 'should allow Enqueue.task and appending Enqueue' do
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
521
|
+
task_json = '{"account_sid": "AC123123123"}'
|
|
522
|
+
expected_doc = parse <<-XML
|
|
523
|
+
<Response>
|
|
524
|
+
<Enqueue workflowSid="123123123">
|
|
525
|
+
<Task>#{task_json}</Task>
|
|
526
|
+
</Enqueue>
|
|
527
|
+
</Response>
|
|
528
|
+
XML
|
|
529
|
+
enqueue_elem = Twilio::TwiML::Enqueue.new(name: nil, workflow_sid: '123123123')
|
|
530
|
+
enqueue_elem.task(task_json)
|
|
531
|
+
|
|
532
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
533
|
+
response.append(enqueue_elem)
|
|
534
|
+
doc = parse(response)
|
|
535
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
326
536
|
end
|
|
327
537
|
|
|
328
538
|
it 'should allow Enqueue.task with a dictionary and appending Enqueue' do
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
539
|
+
expected_doc = parse <<-XML
|
|
540
|
+
<Response>
|
|
541
|
+
<Enqueue workflowSid="123123123">
|
|
542
|
+
<Task>{"account_sid":"AC123123123"}</Task>
|
|
543
|
+
</Enqueue>
|
|
544
|
+
</Response>
|
|
545
|
+
XML
|
|
546
|
+
enqueue_elem = Twilio::TwiML::Enqueue.new(name: nil, workflow_sid: '123123123')
|
|
547
|
+
enqueue_elem.task(account_sid: 'AC123123123')
|
|
548
|
+
|
|
549
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
550
|
+
response.append(enqueue_elem)
|
|
551
|
+
|
|
552
|
+
doc = parse(response)
|
|
553
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
336
554
|
end
|
|
337
555
|
end
|
|
338
556
|
|
|
339
557
|
context 'Testing Dial' do
|
|
340
558
|
it 'should allow VoiceResponse.dial' do
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
559
|
+
expected_doc = parse <<-XML
|
|
560
|
+
<Response>
|
|
561
|
+
<Dial>1231231234</Dial>
|
|
562
|
+
</Response>
|
|
563
|
+
XML
|
|
564
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
565
|
+
response.dial(number: '1231231234')
|
|
566
|
+
doc = parse(response)
|
|
567
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
345
568
|
end
|
|
346
569
|
|
|
347
570
|
it 'should allow Dial.sim' do
|
|
348
|
-
|
|
349
|
-
|
|
571
|
+
expected_doc = parse <<-XML
|
|
572
|
+
<Response>
|
|
573
|
+
<Dial>
|
|
574
|
+
<Sim>123123123</Sim>
|
|
575
|
+
</Dial>
|
|
576
|
+
</Response>
|
|
577
|
+
XML
|
|
578
|
+
dial = Twilio::TwiML::Dial.new
|
|
579
|
+
dial.sim '123123123'
|
|
350
580
|
|
|
351
|
-
|
|
352
|
-
|
|
581
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
582
|
+
response.append(dial)
|
|
353
583
|
|
|
354
|
-
|
|
584
|
+
doc = parse(response)
|
|
585
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
355
586
|
end
|
|
356
587
|
|
|
357
588
|
it 'should allow Dial.sip' do
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
589
|
+
expected_doc = parse <<-XML
|
|
590
|
+
<Response>
|
|
591
|
+
<Dial>
|
|
592
|
+
<Sip>foo@example.com</Sip>
|
|
593
|
+
</Dial>
|
|
594
|
+
</Response>
|
|
595
|
+
XML
|
|
596
|
+
dial = Twilio::TwiML::Dial.new
|
|
597
|
+
dial.sip 'foo@example.com'
|
|
598
|
+
|
|
599
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
600
|
+
response.append(dial)
|
|
601
|
+
doc = parse(response)
|
|
602
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
365
603
|
end
|
|
366
604
|
|
|
367
605
|
it 'should allow Dial.sip with username, password' do
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
606
|
+
expected_doc = parse <<-XML
|
|
607
|
+
<Response>
|
|
608
|
+
<Dial>
|
|
609
|
+
<Sip username="foo" password="bar">foo@example.com</Sip>
|
|
610
|
+
</Dial>
|
|
611
|
+
</Response>
|
|
612
|
+
XML
|
|
613
|
+
dial = Twilio::TwiML::Dial.new
|
|
614
|
+
dial.sip('foo@example.com', username: 'foo', password: 'bar')
|
|
615
|
+
|
|
616
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
617
|
+
response.append(dial)
|
|
618
|
+
doc = parse(response)
|
|
619
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
375
620
|
end
|
|
376
621
|
|
|
377
622
|
it 'should allow Dial.number' do
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
623
|
+
expected_doc = parse <<-XML
|
|
624
|
+
<Response>
|
|
625
|
+
<Dial>
|
|
626
|
+
<Number>1231231234</Number>
|
|
627
|
+
</Dial>
|
|
628
|
+
</Response>
|
|
629
|
+
XML
|
|
630
|
+
dial = Twilio::TwiML::Dial.new
|
|
631
|
+
dial.number '1231231234'
|
|
632
|
+
|
|
633
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
634
|
+
response.append(dial)
|
|
635
|
+
doc = parse(response)
|
|
636
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
385
637
|
end
|
|
386
638
|
|
|
387
639
|
it 'should allow Dial.number with params' do
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
640
|
+
expected_doc = parse <<-XML
|
|
641
|
+
<Response>
|
|
642
|
+
<Dial>
|
|
643
|
+
<Number statusCallback="http://example.com" statusCallbackEvent="initiated completed">1231231234</Number>
|
|
644
|
+
</Dial>
|
|
645
|
+
</Response>
|
|
646
|
+
XML
|
|
647
|
+
dial = Twilio::TwiML::Dial.new
|
|
648
|
+
dial.number('1231231234', status_callback: 'http://example.com', status_callback_event: 'initiated completed')
|
|
649
|
+
|
|
650
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
651
|
+
response.append(dial)
|
|
652
|
+
doc = parse(response)
|
|
653
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
395
654
|
end
|
|
396
655
|
|
|
397
656
|
it 'should allow Dial.conference' do
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
657
|
+
expected_doc = parse <<-XML
|
|
658
|
+
<Response>
|
|
659
|
+
<Dial>
|
|
660
|
+
<Conference>My Room</Conference>
|
|
661
|
+
</Dial>
|
|
662
|
+
</Response>
|
|
663
|
+
XML
|
|
664
|
+
dial = Twilio::TwiML::Dial.new
|
|
665
|
+
dial.conference 'My Room'
|
|
666
|
+
|
|
667
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
668
|
+
response.append(dial)
|
|
669
|
+
doc = parse(response)
|
|
670
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
405
671
|
end
|
|
406
672
|
|
|
407
673
|
it 'should allow Dial.queue' do
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
674
|
+
expected_doc = parse <<-XML
|
|
675
|
+
<Response>
|
|
676
|
+
<Dial>
|
|
677
|
+
<Queue>The Cute Queue</Queue>
|
|
678
|
+
</Dial>
|
|
679
|
+
</Response>
|
|
680
|
+
XML
|
|
681
|
+
dial = Twilio::TwiML::Dial.new
|
|
682
|
+
dial.queue 'The Cute Queue'
|
|
683
|
+
|
|
684
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
685
|
+
response.append(dial)
|
|
686
|
+
doc = parse(response)
|
|
687
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
415
688
|
end
|
|
416
689
|
|
|
417
690
|
it 'should allow empty Dial.client' do
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
691
|
+
expected_doc = parse <<-XML
|
|
692
|
+
<Response>
|
|
693
|
+
<Dial>
|
|
694
|
+
<Client></Client>
|
|
695
|
+
</Dial>
|
|
696
|
+
</Response>
|
|
697
|
+
XML
|
|
698
|
+
dial = Twilio::TwiML::Dial.new
|
|
699
|
+
dial.client ''
|
|
700
|
+
|
|
701
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
702
|
+
response.append(dial)
|
|
703
|
+
doc = parse(response)
|
|
704
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
429
705
|
end
|
|
430
706
|
|
|
431
707
|
it 'should allow populated Dial.client' do
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
708
|
+
expected_doc = parse <<-XML
|
|
709
|
+
<Response>
|
|
710
|
+
<Dial>
|
|
711
|
+
<Client>alice</Client>
|
|
712
|
+
</Dial>
|
|
713
|
+
</Response>
|
|
714
|
+
XML
|
|
715
|
+
dial = Twilio::TwiML::Dial.new
|
|
716
|
+
dial.client 'alice'
|
|
717
|
+
|
|
718
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
719
|
+
response.append(dial)
|
|
720
|
+
doc = parse(response)
|
|
721
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
439
722
|
end
|
|
440
723
|
end
|
|
441
724
|
|
|
442
725
|
context 'Testing Gather' do
|
|
443
726
|
it 'should allow empty Gather' do
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
727
|
+
expected_doc = parse <<-XML
|
|
728
|
+
<Response>
|
|
729
|
+
<Gather></Gather>
|
|
730
|
+
</Response>
|
|
731
|
+
XML
|
|
732
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
733
|
+
response.gather
|
|
734
|
+
doc = parse(response)
|
|
735
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
736
|
+
end
|
|
737
|
+
|
|
738
|
+
it 'should allow nested Say in Gather' do
|
|
739
|
+
expected_doc = parse <<-XML
|
|
740
|
+
<Response>
|
|
741
|
+
<Gather>
|
|
742
|
+
<Say>Hello</Say>
|
|
743
|
+
</Gather>
|
|
744
|
+
</Response>
|
|
745
|
+
XML
|
|
746
|
+
gather_elem = Twilio::TwiML::Gather.new
|
|
747
|
+
gather_elem.say 'Hello'
|
|
748
|
+
|
|
749
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
750
|
+
response.append(gather_elem)
|
|
751
|
+
doc = parse(response)
|
|
752
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
458
753
|
end
|
|
459
754
|
|
|
460
755
|
it 'should allow nested play and pause' do
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
756
|
+
expected_doc = parse <<-XML
|
|
757
|
+
<Response>
|
|
758
|
+
<Gather>
|
|
759
|
+
<Say>Hey</Say>
|
|
760
|
+
<Play>hey.mp3</Play>
|
|
761
|
+
<Pause/>
|
|
762
|
+
</Gather>
|
|
763
|
+
</Response>
|
|
764
|
+
XML
|
|
765
|
+
gather = Twilio::TwiML::Gather.new
|
|
766
|
+
gather.say 'Hey'
|
|
767
|
+
gather.play(url: 'hey.mp3')
|
|
768
|
+
gather.pause
|
|
769
|
+
|
|
770
|
+
response = Twilio::TwiML::VoiceResponse.new
|
|
771
|
+
response.append(gather)
|
|
772
|
+
doc = parse(response)
|
|
773
|
+
expect(doc).to be_equivalent_to(expected_doc).respecting_element_order
|
|
477
774
|
end
|
|
478
775
|
end
|
|
479
776
|
end
|