twiml_template 1.0.2 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4af309b6c6736f4f9eed4acc24e27837c8188b21
4
- data.tar.gz: a241212990c005205f5d97f39d8529710e0a9101
2
+ SHA256:
3
+ metadata.gz: 70c352b6849e64cf30ea1e3dab35d060fdc961e635c5380c12f444d768662fd6
4
+ data.tar.gz: 9e9bb460a33f6dc7fcca759f2dad6a30cc69059f8c277f0ac3dfaede7de7942b
5
5
  SHA512:
6
- metadata.gz: b09e1cc323cb3d876a6a773df7c05f0331811a140ed77f5e2c0ef1ebb30a154c0815bfbddb0dcfbfb7edfaae8b23609d4afd1f80a969bc12514ba27be1f17ef9
7
- data.tar.gz: aacea298860c0dc5e3e54df8e6f5e91ec86a53c2f5ecc70ef83de78147b01e77e3956887a833984f87d7f8f3dadf02082f19345ec817d7d639845c2a5bd062b6
6
+ metadata.gz: 821ae351940fc9480100d601626466cc9d499c9bb6f6fd464a6e38e61fb17b66efba15cb89ba7f2d5ef89dfdbbbb5081ae522e46c97d10bc127eeca74fea684c
7
+ data.tar.gz: 2db082586c4f781174b1ccff270c476bc418f9bd89c3225a038746e2a34c1976af97c6e74a6592f0b6adbbe2975428e1ad6f069671b56f5e4c270091fef36d66
data/.travis.yml CHANGED
@@ -1,12 +1,27 @@
1
1
  language: ruby
2
- before_install: gem install bundler
2
+ sudo: required
3
+ dist: trusty
4
+ before_install:
5
+ - gem update --system
6
+ - gem install bundler
3
7
  install:
4
8
  - bundle install --retry=3
5
9
  cache: bundler
6
10
  rvm:
7
- - 1.9.3
8
- - 2.0.0
9
- - 2.1.0
10
- - 2.2.0
11
+ - 2.4
12
+ - 2.5
13
+ - 2.6
14
+ - ruby-head
15
+ - jruby-18mode
11
16
  - jruby-19mode
12
- - rbx
17
+ - jruby-head
18
+ - rbx-3
19
+ matrix:
20
+ allow_failures:
21
+ - rvm: rbx-3
22
+ - rvm: ruby-head
23
+ - rvm: jruby-head
24
+ addons:
25
+ apt:
26
+ packages:
27
+ - haveged
data/README.md CHANGED
@@ -2,10 +2,29 @@
2
2
 
3
3
  [TwiML](https://www.twilio.com/docs/api/twiml) templates for Tilt.
4
4
 
5
- An easy way to work with TwiML for responding to [Twilio](http://twilio.com) webhooks in Rails or Sinatra applications using template files.
5
+ An easy way to work with TwiML for responding to [Twilio](http://twilio.com) webhooks in Rails or Sinatra applications using template files with a `.twiml` extension.
6
6
 
7
7
  [![Build Status](https://travis-ci.org/philnash/twiml_template.svg)](https://travis-ci.org/philnash/twiml_template) [![Code Climate](https://codeclimate.com/github/philnash/twiml_template/badges/gpa.svg)](https://codeclimate.com/github/philnash/twiml_template)
8
8
 
9
+ ## Example
10
+
11
+ If you create a template called `hello_world.twiml` with the following code:
12
+
13
+ ```ruby
14
+ twiml.say(message: "Hello World!")
15
+ ```
16
+
17
+ and rendered it from an application you would get the following response:
18
+
19
+ ```xml
20
+ <?xml version="1.0" encoding="UTF-8"?>
21
+ <Response>
22
+ <Say>Hello World!</Say>
23
+ </Response>
24
+ ```
25
+
26
+ See [Rails](#rails) or [Sinatra](#sinatra) below for full instructions.
27
+
9
28
  ## Installation
10
29
 
11
30
  Add this line to your application's Gemfile:
@@ -16,7 +35,7 @@ gem 'twiml_template'
16
35
 
17
36
  And then execute:
18
37
 
19
- $ bundle
38
+ $ bundle install
20
39
 
21
40
  Or install it yourself as:
22
41
 
@@ -24,6 +43,10 @@ Or install it yourself as:
24
43
 
25
44
  ## Usage
26
45
 
46
+ `twiml_template` allows you to use a template with the extension `.twiml` to write TwiML. The template makes a single variable, `twiml` available. `twiml` is an instance of a `TwimlTemplate::Response` which unifies the `twilio-ruby` gem's `Twilio::TwiML::VoiceResponse` and `Twilio::TwiML::MessagingResponse` classes. This means you only need one type of template file, but you can use it for either voice or messaging responses. `twiml_template` passes methods through to objects of each of those classes to generate the response.
47
+
48
+ If you start writing a voice response, you can only continue writing a voice response. If you start writing a messaging response, you can only continue with a messaging response. This should never cause you a problem (you would never normally write a response with a `<Say>` and a `<Message>` in it!).
49
+
27
50
  ### Rails
28
51
 
29
52
  By including the `twiml_template` gem in your Rails project Gemfile you will be able to write TwiML templates easily.
@@ -51,7 +74,7 @@ end
51
74
  And then add your TwiML view:
52
75
 
53
76
  ```ruby
54
- twiml.Say "Hello #{@name}"
77
+ twiml.say message: "Hello #{@name}"
55
78
  ```
56
79
 
57
80
  Save the file as `#{RAILS_ROOT}/app/views/voice/index.twiml`.
@@ -84,7 +107,7 @@ end
84
107
  And then add your TwiML view:
85
108
 
86
109
  ```ruby
87
- twiml.Say "Hello #{@name}"
110
+ twiml.say "Hello #{@name}"
88
111
  ```
89
112
 
90
113
  Save the file as `#{APP_ROOT}/views/voice.twiml`.
data/Rakefile CHANGED
@@ -7,5 +7,5 @@ desc 'Run tests (default)'
7
7
  Rake::TestTask.new(:spec) do |t|
8
8
  t.test_files = FileList['spec/**/*_spec.rb']
9
9
  t.ruby_opts = ['-Ispec']
10
- t.ruby_opts << '-rubygems' if defined? Gem
10
+ t.ruby_opts << '-r rubygems' if defined? Gem
11
11
  end
@@ -3,9 +3,9 @@ require 'twilio-ruby'
3
3
  module ActionView
4
4
  module Template::Handlers
5
5
  class TwiML
6
- def self.call(template)
6
+ def self.call(template, source = nil)
7
7
  "self.output_buffer = ::Twilio::TwiML::Response.new do |twiml|;" +
8
- template.source +
8
+ (source || template.source) +
9
9
  ";end.to_xml;"
10
10
  end
11
11
  end
data/lib/tilt/twiml.rb CHANGED
@@ -9,7 +9,7 @@ module Tilt
9
9
 
10
10
  def evaluate(scope, locals, &block)
11
11
  return super(scope, locals, &block) if data.respond_to?(:to_str)
12
- twiml = ::Twilio::TwiML::Response.new do |response|
12
+ ::TwimlTemplate::Response.new do |response|
13
13
  data.call(response)
14
14
  end.to_xml
15
15
  end
@@ -20,7 +20,7 @@ module Tilt
20
20
 
21
21
  def precompiled_preamble(locals)
22
22
  return super if locals.include? :twiml
23
- "::Twilio::TwiML::Response.new do |twiml|\n#{super}"
23
+ "::TwimlTemplate::Response.new do |twiml|\n#{super}"
24
24
  end
25
25
 
26
26
  def precompiled_postamble(locals)
@@ -0,0 +1,45 @@
1
+ module TwimlTemplate
2
+ class Response
3
+ MESSAGING_VERBS = [:message, :redirect]
4
+ VOICE_VERBS = [:say, :play, :dial, :gather, :pause, :enqueue, :hangup, :leave, :record, :redirect, :reject, :sms, :connect, :autopilot, :pay, :start]
5
+
6
+ def initialize
7
+ @voice_response = Twilio::TwiML::VoiceResponse.new
8
+ @messaging_response = Twilio::TwiML::MessagingResponse.new
9
+
10
+ yield(self) if block_given?
11
+ end
12
+
13
+ def to_xml
14
+ twiml_response = @messaging_response || @voice_response
15
+ twiml_response.to_xml
16
+ end
17
+
18
+ def method_missing(method, *args, &block)
19
+ if (respond_to?(method))
20
+ if (MESSAGING_VERBS.include?(method.to_sym) && @messaging_response)
21
+ if ((MESSAGING_VERBS - VOICE_VERBS).include?(method.to_sym))
22
+ @voice_response = nil
23
+ end
24
+ @messaging_response.send(method.to_sym, *args, &block)
25
+ end
26
+ if (VOICE_VERBS.include?(method.to_sym) && @voice_response)
27
+ if ((VOICE_VERBS - MESSAGING_VERBS).include?(method.to_sym))
28
+ @messaging_response = nil
29
+ end
30
+ @voice_response.send(method.to_sym, *args, &block)
31
+ end
32
+ else
33
+ raise ArgumentError.new("Method `#{method}` doesn't exist.")
34
+ end
35
+ return @messaging_response || @voice_response
36
+ end
37
+
38
+ def respond_to?(method, include_private = false)
39
+ verbs = []
40
+ verbs = verbs | MESSAGING_VERBS if @messaging_response
41
+ verbs = verbs | VOICE_VERBS if @voice_response
42
+ verbs.include?(method.to_sym) || super
43
+ end
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
1
  module TwimlTemplate
2
- VERSION = "1.0.2"
2
+ VERSION = "2.0.0.pre"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require 'twiml_template/version'
2
+ require 'twiml_template/response'
2
3
 
3
4
  if defined? Rails
4
5
  require 'twiml_template/railtie'
@@ -0,0 +1,22 @@
1
+ require 'minitest/assertions'
2
+ require 'minitest/spec'
3
+ require 'equivalent-xml'
4
+ require 'nokogiri'
5
+
6
+ module Minitest::Assertions
7
+ def assert_equivalent_xml(expected, actual)
8
+ expected = parse(expected) unless expected.is_a?(Nokogiri::XML::Document)
9
+ actual = parse(actual) unless actual.is_a?(Nokogiri::XML::Document)
10
+ assert EquivalentXml.equivalent?(expected, actual, opts = { :element_order => true, :normalize_whitespace => false }), "Expected XML to be equivalent. Expected:\n\n#{expected.to_s} \n\nReceived:\n\n#{actual.to_s}"
11
+ end
12
+
13
+ private
14
+
15
+ def parse(string)
16
+ Nokogiri::XML::Document.parse(string.to_s, &:noblanks)
17
+ end
18
+ end
19
+
20
+ module Minitest::Expectations
21
+ String.infect_an_assertion :assert_equivalent_xml, :must_be_equivalent_xml
22
+ end
@@ -24,6 +24,6 @@ describe Sinatra::TwiML do
24
24
 
25
25
  it "renders simple template" do
26
26
  response = get("/hello")
27
- response.body.strip.must_equal twiml_response
27
+ response.body.strip.must_be_equivalent_xml(twiml_response)
28
28
  end
29
29
  end
@@ -1 +1 @@
1
- twiml.Say "Hello #{name}!"
1
+ twiml.say message: "Hello #{name}!"
data/spec/spec_helper.rb CHANGED
@@ -5,3 +5,4 @@ Bundler.setup
5
5
 
6
6
  require 'minitest/autorun'
7
7
  require 'minitest/mock'
8
+ require_relative './custom_assertions.rb'
@@ -14,13 +14,13 @@ describe Tilt::TwiML do
14
14
  end
15
15
 
16
16
  it "prepares and evaluates the template on #render" do
17
- template = Tilt::TwiML.new { |t| "twiml.Say 'Hello World!'" }
18
- template.render.must_equal twiml_response
17
+ template = Tilt::TwiML.new { |t| "twiml.say message: 'Hello World!'" }
18
+ template.render.must_be_equivalent_xml twiml_response
19
19
  end
20
20
 
21
21
  it "can be rendered more than once" do
22
- template = Tilt::TwiML.new { |t| "twiml.Say 'Hello World!'" }
23
- 3.times { template.render.must_equal twiml_response }
22
+ template = Tilt::TwiML.new { |t| "twiml.say message: 'Hello World!'" }
23
+ 3.times { template.render.must_be_equivalent_xml twiml_response }
24
24
  end
25
25
  end
26
26
 
@@ -33,44 +33,33 @@ describe Tilt::TwiML do
33
33
 
34
34
  it "passes locals" do
35
35
  template = Tilt::TwiML.new do |t|
36
- "twiml.Say 'Hello ' + name + '!'"
36
+ "twiml.say message: 'Hello ' + name + '!'"
37
37
  end
38
- template.render(Object.new, :name => 'Joe').must_equal twiml_response
38
+ template.render(Object.new, :name => 'Joe').must_be_equivalent_xml twiml_response
39
39
  end
40
40
 
41
41
  it "evaluates in an object scope" do
42
42
  template = Tilt::TwiML.new do |t|
43
- "twiml.Say 'Hello ' + @name + '!'"
43
+ "twiml.say message: 'Hello ' + @name + '!'"
44
44
  end
45
45
  scope = Object.new
46
46
  scope.instance_variable_set :@name, 'Joe'
47
- template.render(scope).must_equal twiml_response
47
+ template.render(scope).must_be_equivalent_xml twiml_response
48
48
  end
49
49
 
50
50
  it "passes a block for yield" do
51
51
  template = Tilt::TwiML.new do |t|
52
- "twiml.Say 'Hello ' + yield + '!'"
52
+ "twiml.say message: 'Hello ' + yield + '!'"
53
53
  end
54
- 3.times { template.render { 'Joe' }.must_equal twiml_response }
54
+ 3.times { template.render { 'Joe' }.must_be_equivalent_xml twiml_response }
55
55
  end
56
56
 
57
57
  it "takes block style templates" do
58
58
  template =
59
59
  Tilt::TwiML.new do |t|
60
- lambda { |twiml| twiml.Say('Hello Joe!') }
60
+ lambda { |twiml| twiml.say(message: 'Hello Joe!') }
61
61
  end
62
- template.render.must_equal twiml_response
62
+ template.render.must_be_equivalent_xml twiml_response
63
63
  end
64
-
65
- it "allows nesting raw XML" do
66
- subtemplate = '<Number>+447712345678</Number>'
67
- template = Tilt::TwiML.new { "twiml.Dial { twiml << yield }" }
68
- expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response>" \
69
- "<Dial><Number>+447712345678</Number></Dial></Response>"
70
- 3.times do
71
- template.render { subtemplate }.must_equal expected
72
- end
73
- end
74
-
75
64
  end
76
65
  end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+ require 'twiml_template/response'
3
+
4
+ describe TwimlTemplate::Response do
5
+ let(:response) { TwimlTemplate::Response.new }
6
+
7
+ describe 'with a messaging response' do
8
+ describe 'with a simple response' do
9
+ let :twiml do
10
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response>" \
11
+ "<Message>Hello World!</Message></Response>"
12
+ end
13
+
14
+ it 'generates successfully' do
15
+ response.message(body: "Hello World!")
16
+ response.to_xml.must_be_equivalent_xml twiml
17
+ end
18
+
19
+ [:message, :redirect].each do |verb|
20
+ it "responds to #{verb}" do
21
+ response.must_respond_to(verb)
22
+ end
23
+ end
24
+ end
25
+
26
+ describe 'with a nested response' do
27
+ let :twiml do
28
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response>" \
29
+ "<Message><Body>Hello World!</Body></Message></Response>"
30
+ end
31
+
32
+ it 'generates successfully' do
33
+ response.message do |msg|
34
+ msg.body "Hello World!"
35
+ end
36
+ response.to_xml.must_be_equivalent_xml twiml
37
+ end
38
+ end
39
+
40
+ describe 'with multiple commands' do
41
+ let :twiml do
42
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response>" \
43
+ "<Message>Hello World!</Message><Redirect>http://example.com</Redirect></Response>"
44
+ end
45
+
46
+ it 'generates successfully' do
47
+ response.message(body: "Hello World!")
48
+ response.redirect("http://example.com")
49
+ response.to_xml.must_be_equivalent_xml twiml
50
+ end
51
+ end
52
+ end
53
+
54
+ describe 'with a voice response' do
55
+ describe 'with a simple response' do
56
+ let :twiml do
57
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response>" \
58
+ "<Say>Hello World!</Say></Response>"
59
+ end
60
+
61
+ it 'generates successfully' do
62
+ response.say(message: "Hello World!")
63
+ response.to_xml.must_be_equivalent_xml twiml
64
+ end
65
+
66
+ (TwimlTemplate::Response::MESSAGING_VERBS | TwimlTemplate::Response::VOICE_VERBS).each do |verb|
67
+ it "responds to #{verb}" do
68
+ response.must_respond_to(verb)
69
+ end
70
+ end
71
+ end
72
+
73
+ describe 'with a nested response' do
74
+ let :twiml do
75
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response>" \
76
+ "<Gather><Say>Hello World!</Say></Gather></Response>"
77
+ end
78
+
79
+ it 'generates successfully' do
80
+ response.gather do |gather|
81
+ gather.say message: "Hello World!"
82
+ end
83
+ response.to_xml.must_be_equivalent_xml twiml
84
+ end
85
+ end
86
+
87
+ describe 'with multiple commands' do
88
+ let :twiml do
89
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response>" \
90
+ "<Say>Hello World!</Say><Play>http://tunes.com</Play></Response>"
91
+ end
92
+
93
+ it 'generates successfully' do
94
+ response.say(message: "Hello World!")
95
+ response.play(url: "http://tunes.com")
96
+ response.to_xml.must_be_equivalent_xml twiml
97
+ end
98
+ end
99
+ end
100
+
101
+ describe 'with a mixed response' do
102
+ it 'should raise an error' do
103
+ proc do
104
+ response.say(message: "Hello")
105
+ response.message(" World!")
106
+ end.must_raise ArgumentError
107
+ end
108
+
109
+ it 'should allow a redirect and a message' do
110
+ proc do
111
+ response.redirect("http://example.com")
112
+ response.message(body: "Hello World!")
113
+ end.must_be_silent
114
+ end
115
+
116
+ it 'should allow a redirect and a voice verb' do
117
+ proc do
118
+ response.redirect("http://example.com")
119
+ response.say(message: "Hello World!")
120
+ end.must_be_silent
121
+ end
122
+ end
123
+ end
@@ -20,11 +20,12 @@ Gem::Specification.new do |spec|
20
20
  spec.required_ruby_version = '>= 1.9.3'
21
21
 
22
22
  spec.add_dependency "tilt", ">= 1.3", "< 3"
23
- spec.add_dependency "twilio-ruby", ">= 3.0", "< 5.0"
23
+ spec.add_dependency "twilio-ruby", ">= 5.28", "< 6.0"
24
24
 
25
- spec.add_development_dependency "bundler", "~> 1.7"
25
+ spec.add_development_dependency "bundler", ">= 1.7", "< 3.0"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
27
  spec.add_development_dependency "minitest", "~> 5.0"
28
28
  spec.add_development_dependency "rack-test"
29
29
  spec.add_development_dependency "sinatra", ">= 1.3"
30
+ spec.add_development_dependency "equivalent-xml", "~> 0.6.0"
30
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twiml_template
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 2.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Nash
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-29 00:00:00.000000000 Z
11
+ date: 2019-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tilt
@@ -36,34 +36,40 @@ dependencies:
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: '3.0'
39
+ version: '5.28'
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: '5.0'
42
+ version: '6.0'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: '3.0'
49
+ version: '5.28'
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: '5.0'
52
+ version: '6.0'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: bundler
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
- - - "~>"
57
+ - - ">="
58
58
  - !ruby/object:Gem::Version
59
59
  version: '1.7'
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.0'
60
63
  type: :development
61
64
  prerelease: false
62
65
  version_requirements: !ruby/object:Gem::Requirement
63
66
  requirements:
64
- - - "~>"
67
+ - - ">="
65
68
  - !ruby/object:Gem::Version
66
69
  version: '1.7'
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '3.0'
67
73
  - !ruby/object:Gem::Dependency
68
74
  name: rake
69
75
  requirement: !ruby/object:Gem::Requirement
@@ -120,6 +126,20 @@ dependencies:
120
126
  - - ">="
121
127
  - !ruby/object:Gem::Version
122
128
  version: '1.3'
129
+ - !ruby/object:Gem::Dependency
130
+ name: equivalent-xml
131
+ requirement: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: 0.6.0
136
+ type: :development
137
+ prerelease: false
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: 0.6.0
123
143
  description: An easy way to work with TwiML for responding to Twilio webhooks in Rails
124
144
  or Sinatra applications using template files.
125
145
  email:
@@ -139,11 +159,14 @@ files:
139
159
  - lib/tilt/twiml.rb
140
160
  - lib/twiml_template.rb
141
161
  - lib/twiml_template/railtie.rb
162
+ - lib/twiml_template/response.rb
142
163
  - lib/twiml_template/version.rb
164
+ - spec/custom_assertions.rb
143
165
  - spec/sinatra/twiml_spec.rb
144
166
  - spec/sinatra/views/hello.twiml
145
167
  - spec/spec_helper.rb
146
168
  - spec/tilt/twiml_spec.rb
169
+ - spec/twiml_template/response_spec.rb
147
170
  - twiml_template.gemspec
148
171
  homepage: https://github.com/philnash/twiml_template
149
172
  licenses:
@@ -160,17 +183,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
160
183
  version: 1.9.3
161
184
  required_rubygems_version: !ruby/object:Gem::Requirement
162
185
  requirements:
163
- - - ">="
186
+ - - ">"
164
187
  - !ruby/object:Gem::Version
165
- version: '0'
188
+ version: 1.3.1
166
189
  requirements: []
167
- rubyforge_project:
168
- rubygems_version: 2.6.6
190
+ rubygems_version: 3.0.3
169
191
  signing_key:
170
192
  specification_version: 4
171
193
  summary: TwiML templates for Rails and Tilt.
172
194
  test_files:
195
+ - spec/custom_assertions.rb
173
196
  - spec/sinatra/twiml_spec.rb
174
197
  - spec/sinatra/views/hello.twiml
175
198
  - spec/spec_helper.rb
176
199
  - spec/tilt/twiml_spec.rb
200
+ - spec/twiml_template/response_spec.rb