ruby_speech 2.3.1 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.hound.yml +2 -0
- data/.travis.yml +25 -9
- data/CHANGELOG.md +19 -1
- data/README.md +14 -15
- data/Rakefile +2 -0
- data/ext/ruby_speech/RubySpeechGRXMLMatcher.java +17 -12
- data/ext/ruby_speech/RubySpeechService.java +1 -1
- data/ext/ruby_speech/extconf.rb +1 -1
- data/lib/ruby_speech/generic_element.rb +2 -2
- data/lib/ruby_speech/grxml/builtins.rb +18 -11
- data/lib/ruby_speech/grxml/grammar.rb +26 -4
- data/lib/ruby_speech/grxml/matcher.rb +2 -2
- data/lib/ruby_speech/grxml.rb +2 -0
- data/lib/ruby_speech/nlsml/builder.rb +2 -1
- data/lib/ruby_speech/nlsml/document.rb +5 -0
- data/lib/ruby_speech/ssml/break.rb +1 -2
- data/lib/ruby_speech/ssml/element.rb +13 -1
- data/lib/ruby_speech/ssml/mark.rb +0 -1
- data/lib/ruby_speech/ssml/prosody.rb +8 -5
- data/lib/ruby_speech/version.rb +1 -1
- data/ruby_speech.gemspec +13 -8
- data/spec/ruby_speech/grxml/builtins_spec.rb +80 -71
- data/spec/ruby_speech/grxml/grammar_spec.rb +168 -34
- data/spec/ruby_speech/grxml/item_spec.rb +33 -33
- data/spec/ruby_speech/grxml/match_spec.rb +1 -1
- data/spec/ruby_speech/grxml/matcher_spec.rb +103 -59
- data/spec/ruby_speech/grxml/max_match_spec.rb +2 -2
- data/spec/ruby_speech/grxml/no_match_spec.rb +2 -2
- data/spec/ruby_speech/grxml/one_of_spec.rb +6 -6
- data/spec/ruby_speech/grxml/potential_match_spec.rb +2 -2
- data/spec/ruby_speech/grxml/rule_spec.rb +17 -17
- data/spec/ruby_speech/grxml/ruleref_spec.rb +10 -10
- data/spec/ruby_speech/grxml/tag_spec.rb +5 -5
- data/spec/ruby_speech/grxml/token_spec.rb +7 -7
- data/spec/ruby_speech/grxml_spec.rb +25 -25
- data/spec/ruby_speech/nlsml_spec.rb +58 -10
- data/spec/ruby_speech/ssml/audio_spec.rb +19 -19
- data/spec/ruby_speech/ssml/break_spec.rb +42 -22
- data/spec/ruby_speech/ssml/desc_spec.rb +7 -7
- data/spec/ruby_speech/ssml/emphasis_spec.rb +21 -21
- data/spec/ruby_speech/ssml/mark_spec.rb +5 -5
- data/spec/ruby_speech/ssml/p_spec.rb +17 -17
- data/spec/ruby_speech/ssml/phoneme_spec.rb +8 -8
- data/spec/ruby_speech/ssml/prosody_spec.rb +82 -64
- data/spec/ruby_speech/ssml/s_spec.rb +16 -16
- data/spec/ruby_speech/ssml/say_as_spec.rb +9 -9
- data/spec/ruby_speech/ssml/speak_spec.rb +29 -29
- data/spec/ruby_speech/ssml/sub_spec.rb +7 -7
- data/spec/ruby_speech/ssml/voice_spec.rb +31 -31
- data/spec/ruby_speech/ssml_spec.rb +41 -17
- data/spec/ruby_speech_spec.rb +3 -3
- data/spec/spec_helper.rb +8 -3
- data/spec/support/dtmf_helper.rb +14 -0
- data/spec/support/grammar_matchers.rb +6 -6
- data/spec/support/match_examples.rb +5 -5
- data/spec/support/matchers.rb +1 -1
- metadata +49 -20
@@ -4,22 +4,22 @@ describe RubySpeech::GRXML::Builtins do
|
|
4
4
|
describe "boolean" do
|
5
5
|
subject(:grammar) { described_class.boolean }
|
6
6
|
|
7
|
-
it {
|
8
|
-
it {
|
7
|
+
it { is_expected.to max_match('1').and_interpret_as('true') }
|
8
|
+
it { is_expected.to max_match('2').and_interpret_as('false') }
|
9
9
|
|
10
|
-
it {
|
11
|
-
it {
|
12
|
-
it {
|
10
|
+
it { is_expected.to not_match('0') }
|
11
|
+
it { is_expected.to not_match('3') }
|
12
|
+
it { is_expected.to not_match('10') }
|
13
13
|
|
14
14
|
context "with the true/false digits parameterized" do
|
15
15
|
subject { described_class.boolean y: 3, n: 7 }
|
16
16
|
|
17
|
-
it {
|
18
|
-
it {
|
17
|
+
it { is_expected.to max_match('3').and_interpret_as('true') }
|
18
|
+
it { is_expected.to max_match('7').and_interpret_as('false') }
|
19
19
|
|
20
|
-
it {
|
21
|
-
it {
|
22
|
-
it {
|
20
|
+
it { is_expected.to not_match('1') }
|
21
|
+
it { is_expected.to not_match('2') }
|
22
|
+
it { is_expected.to not_match('4') }
|
23
23
|
|
24
24
|
context "both the same" do
|
25
25
|
it "should raise ArgumentError" do
|
@@ -32,54 +32,54 @@ describe RubySpeech::GRXML::Builtins do
|
|
32
32
|
describe "date" do
|
33
33
|
subject(:grammar) { described_class.date }
|
34
34
|
|
35
|
-
it {
|
35
|
+
it { is_expected.to max_match('20130929').and_interpret_as('dtmf-2 dtmf-0 dtmf-1 dtmf-3 dtmf-0 dtmf-9 dtmf-2 dtmf-9') }
|
36
36
|
|
37
|
-
it {
|
38
|
-
it {
|
39
|
-
it {
|
40
|
-
it {
|
37
|
+
it { is_expected.to potentially_match('130929') }
|
38
|
+
it { is_expected.to potentially_match('0929') }
|
39
|
+
it { is_expected.to potentially_match('29') }
|
40
|
+
it { is_expected.to potentially_match('1') }
|
41
41
|
end
|
42
42
|
|
43
43
|
describe "digits" do
|
44
44
|
subject(:grammar) { described_class.digits }
|
45
45
|
|
46
|
-
it {
|
47
|
-
it {
|
48
|
-
it {
|
46
|
+
it { is_expected.to match('1').and_interpret_as('dtmf-1') }
|
47
|
+
it { is_expected.to match('123').and_interpret_as('dtmf-1 dtmf-2 dtmf-3') }
|
48
|
+
it { is_expected.to match('1').and_interpret_as('dtmf-1') }
|
49
49
|
|
50
50
|
context "with a minimum length" do
|
51
51
|
subject { described_class.digits minlength: 3 }
|
52
52
|
|
53
|
-
it {
|
54
|
-
it {
|
53
|
+
it { is_expected.to match('123').and_interpret_as('dtmf-1 dtmf-2 dtmf-3') }
|
54
|
+
it { is_expected.to match('1234567890').and_interpret_as('dtmf-1 dtmf-2 dtmf-3 dtmf-4 dtmf-5 dtmf-6 dtmf-7 dtmf-8 dtmf-9 dtmf-0') }
|
55
55
|
|
56
|
-
it {
|
57
|
-
it {
|
58
|
-
it {
|
56
|
+
it { is_expected.to potentially_match('1') }
|
57
|
+
it { is_expected.to potentially_match('11') }
|
58
|
+
it { is_expected.to potentially_match('4') }
|
59
59
|
end
|
60
60
|
|
61
61
|
context "with a maximum length" do
|
62
62
|
subject { described_class.digits maxlength: 3 }
|
63
63
|
|
64
|
-
it {
|
65
|
-
it {
|
66
|
-
it {
|
64
|
+
it { is_expected.to match('1').and_interpret_as('dtmf-1') }
|
65
|
+
it { is_expected.to match('12').and_interpret_as('dtmf-1 dtmf-2') }
|
66
|
+
it { is_expected.to match('123').and_interpret_as('dtmf-1 dtmf-2 dtmf-3') }
|
67
67
|
|
68
|
-
it {
|
69
|
-
it {
|
68
|
+
it { is_expected.to not_match('1111') }
|
69
|
+
it { is_expected.to not_match('1111111') }
|
70
70
|
end
|
71
71
|
|
72
72
|
context "with an absolute length" do
|
73
73
|
subject { described_class.digits length: 3 }
|
74
74
|
|
75
|
-
it {
|
76
|
-
it {
|
75
|
+
it { is_expected.to max_match('123').and_interpret_as('dtmf-1 dtmf-2 dtmf-3') }
|
76
|
+
it { is_expected.to max_match('111').and_interpret_as('dtmf-1 dtmf-1 dtmf-1') }
|
77
77
|
|
78
|
-
it {
|
79
|
-
it {
|
78
|
+
it { is_expected.to potentially_match('1') }
|
79
|
+
it { is_expected.to potentially_match('12') }
|
80
80
|
|
81
|
-
it {
|
82
|
-
it {
|
81
|
+
it { is_expected.to not_match('1234') }
|
82
|
+
it { is_expected.to not_match('12345') }
|
83
83
|
end
|
84
84
|
|
85
85
|
context "when the min and max lengths are swapped" do
|
@@ -104,62 +104,71 @@ describe RubySpeech::GRXML::Builtins do
|
|
104
104
|
describe "currency" do
|
105
105
|
subject(:grammar) { described_class.currency }
|
106
106
|
|
107
|
-
it {
|
108
|
-
it {
|
109
|
-
it {
|
110
|
-
it {
|
111
|
-
it {
|
107
|
+
it { is_expected.to max_match('1*01').and_interpret_as('dtmf-1 dtmf-star dtmf-0 dtmf-1') }
|
108
|
+
it { is_expected.to max_match('01*00').and_interpret_as('dtmf-0 dtmf-1 dtmf-star dtmf-0 dtmf-0') }
|
109
|
+
it { is_expected.to max_match('100000000000*00').and_interpret_as('dtmf-1 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-0 dtmf-star dtmf-0 dtmf-0') }
|
110
|
+
it { is_expected.to max_match('0*08').and_interpret_as('dtmf-0 dtmf-star dtmf-0 dtmf-8') }
|
111
|
+
it { is_expected.to max_match('*59').and_interpret_as('dtmf-star dtmf-5 dtmf-9') }
|
112
112
|
|
113
|
-
it {
|
114
|
-
it {
|
115
|
-
it {
|
116
|
-
it {
|
117
|
-
it {
|
113
|
+
it { is_expected.to match('0').and_interpret_as('dtmf-0') }
|
114
|
+
it { is_expected.to match('0*0').and_interpret_as('dtmf-0 dtmf-star dtmf-0') }
|
115
|
+
it { is_expected.to match('10*5').and_interpret_as('dtmf-1 dtmf-0 dtmf-star dtmf-5') }
|
116
|
+
it { is_expected.to match('123').and_interpret_as('dtmf-1 dtmf-2 dtmf-3') }
|
117
|
+
it { is_expected.to match('123*').and_interpret_as('dtmf-1 dtmf-2 dtmf-3 dtmf-star') }
|
118
118
|
|
119
|
-
it {
|
119
|
+
it { is_expected.to not_match('#') }
|
120
120
|
end
|
121
121
|
|
122
|
-
describe
|
122
|
+
describe 'number' do
|
123
123
|
subject(:grammar) { described_class.number }
|
124
124
|
|
125
|
-
it {
|
126
|
-
it {
|
127
|
-
it {
|
128
|
-
it {
|
129
|
-
it
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
it {
|
134
|
-
it {
|
135
|
-
it {
|
136
|
-
|
137
|
-
it {
|
125
|
+
it { is_expected.to match('0').and_interpret_as 'dtmf-0' }
|
126
|
+
it { is_expected.to match('123').and_interpret_as 'dtmf-1 dtmf-2 dtmf-3' }
|
127
|
+
it { is_expected.to match('1*01').and_interpret_as dtmf_seq %w(1 star 0 1) }
|
128
|
+
it { is_expected.to match('01*00').and_interpret_as dtmf_seq %w(0 1 star 0 0) }
|
129
|
+
it do
|
130
|
+
is_expected.to match('100000000000*00')
|
131
|
+
.and_interpret_as dtmf_seq %w(1 0 0 0 0 0 0 0 0 0 0 0 star 0 0)
|
132
|
+
end
|
133
|
+
it { is_expected.to match('0*08').and_interpret_as dtmf_seq %w(0 star 0 8) }
|
134
|
+
it { is_expected.to match('*59').and_interpret_as 'dtmf-star dtmf-5 dtmf-9' }
|
135
|
+
it { is_expected.to match('0*0').and_interpret_as 'dtmf-0 dtmf-star dtmf-0' }
|
136
|
+
it { is_expected.to match('10*5').and_interpret_as dtmf_seq %w(1 0 star 5) }
|
137
|
+
it { is_expected.to match('123*').and_interpret_as dtmf_seq %w(1 2 3 star) }
|
138
|
+
it do
|
139
|
+
is_expected.to match('123*2342').and_interpret_as dtmf_seq %w(1 2 3 star 2 3 4 2)
|
140
|
+
end
|
141
|
+
|
142
|
+
it { is_expected.to potentially_match '*' }
|
143
|
+
|
144
|
+
it { is_expected.to not_match '#' }
|
145
|
+
it { is_expected.to not_match '**' }
|
146
|
+
it { is_expected.to not_match '0123*456*789' }
|
138
147
|
end
|
139
148
|
|
140
149
|
describe "phone" do
|
141
150
|
subject(:grammar) { described_class.phone }
|
142
151
|
|
143
|
-
it {
|
144
|
-
it {
|
145
|
-
it {
|
152
|
+
it { is_expected.to match('0').and_interpret_as('dtmf-0') }
|
153
|
+
it { is_expected.to match('0123').and_interpret_as('dtmf-0 dtmf-1 dtmf-2 dtmf-3') }
|
154
|
+
it { is_expected.to match('0123*456').and_interpret_as('dtmf-0 dtmf-1 dtmf-2 dtmf-3 dtmf-star dtmf-4 dtmf-5 dtmf-6') }
|
146
155
|
|
147
|
-
it {
|
156
|
+
it { is_expected.to potentially_match('') }
|
148
157
|
|
149
|
-
it {
|
150
|
-
it {
|
158
|
+
it { is_expected.to not_match('#') }
|
159
|
+
it { is_expected.to not_match('0123*456*789') }
|
151
160
|
end
|
152
161
|
|
153
162
|
describe "time" do
|
154
163
|
subject(:grammar) { described_class.time }
|
155
164
|
|
156
|
-
it {
|
165
|
+
it { is_expected.to max_match('1235').and_interpret_as('dtmf-1 dtmf-2 dtmf-3 dtmf-5') }
|
157
166
|
|
158
|
-
it {
|
159
|
-
it {
|
160
|
-
it {
|
167
|
+
it { is_expected.to match('12').and_interpret_as('dtmf-1 dtmf-2') }
|
168
|
+
it { is_expected.to match('4').and_interpret_as('dtmf-4') }
|
169
|
+
it { is_expected.to match('123').and_interpret_as('dtmf-1 dtmf-2 dtmf-3') }
|
161
170
|
|
162
|
-
it {
|
163
|
-
it {
|
171
|
+
it { is_expected.to not_match('*') }
|
172
|
+
it { is_expected.to not_match('#') }
|
164
173
|
end
|
165
174
|
end
|
@@ -7,7 +7,7 @@ module RubySpeech
|
|
7
7
|
|
8
8
|
subject { described_class.new doc }
|
9
9
|
|
10
|
-
it {
|
10
|
+
it { is_expected.to be_a_valid_grxml_document }
|
11
11
|
|
12
12
|
its(:name) { should == 'grammar' }
|
13
13
|
its(:language) { should == 'en-US' }
|
@@ -36,7 +36,7 @@ module RubySpeech
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'registers itself' do
|
39
|
-
Element.class_from_registration(:grammar).
|
39
|
+
expect(Element.class_from_registration(:grammar)).to eq(Grammar)
|
40
40
|
end
|
41
41
|
|
42
42
|
describe "from a document" do
|
@@ -48,7 +48,7 @@ module RubySpeech
|
|
48
48
|
|
49
49
|
subject { Element.import document }
|
50
50
|
|
51
|
-
it {
|
51
|
+
it { is_expected.to be_instance_of Grammar }
|
52
52
|
|
53
53
|
its(:language) { should == 'jp' }
|
54
54
|
its(:base_uri) { should == 'blah' }
|
@@ -70,24 +70,24 @@ module RubySpeech
|
|
70
70
|
|
71
71
|
describe "comparing objects" do
|
72
72
|
it "should be equal if the content, language and base uri are the same" do
|
73
|
-
Grammar.new(doc, :language => 'en-GB', :base_uri => 'blah', :content => "Hello there").
|
73
|
+
expect(Grammar.new(doc, :language => 'en-GB', :base_uri => 'blah', :content => "Hello there")).to eq(Grammar.new(doc, :language => 'en-GB', :base_uri => 'blah', :content => "Hello there"))
|
74
74
|
end
|
75
75
|
|
76
76
|
describe "when the content is different" do
|
77
77
|
it "should not be equal" do
|
78
|
-
Grammar.new(doc, :content => "Hello").
|
78
|
+
expect(Grammar.new(doc, :content => "Hello")).not_to eq(Grammar.new(doc, :content => "Hello there"))
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
82
|
describe "when the language is different" do
|
83
83
|
it "should not be equal" do
|
84
|
-
Grammar.new(doc, :language => 'en-US').
|
84
|
+
expect(Grammar.new(doc, :language => 'en-US')).not_to eq(Grammar.new(doc, :language => 'en-GB'))
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
88
|
describe "when the base URI is different" do
|
89
89
|
it "should not be equal" do
|
90
|
-
Grammar.new(doc, :base_uri => 'foo').
|
90
|
+
expect(Grammar.new(doc, :base_uri => 'foo')).not_to eq(Grammar.new(doc, :base_uri => 'bar'))
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
@@ -98,7 +98,7 @@ module RubySpeech
|
|
98
98
|
g2 = Grammar.new doc
|
99
99
|
g2 << Rule.new(doc, :id => 'main2')
|
100
100
|
|
101
|
-
g1.
|
101
|
+
expect(g1).not_to eq(g2)
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|
@@ -108,32 +108,32 @@ module RubySpeech
|
|
108
108
|
g.rule :id => :main, :scope => 'public'
|
109
109
|
expected_g = Grammar.new doc
|
110
110
|
expected_g << Rule.new(doc, :id => :main, :scope => 'public')
|
111
|
-
g.
|
111
|
+
expect(g).to eq(expected_g)
|
112
112
|
end
|
113
113
|
|
114
114
|
describe "<<" do
|
115
115
|
it "should accept Rule" do
|
116
|
-
|
116
|
+
expect { subject << Rule.new(doc) }.not_to raise_error
|
117
117
|
end
|
118
118
|
|
119
119
|
it "should accept Tag" do
|
120
|
-
|
120
|
+
expect { subject << Tag.new(doc) }.not_to raise_error
|
121
121
|
end
|
122
122
|
|
123
123
|
it "should raise InvalidChildError with non-acceptable objects" do
|
124
|
-
|
124
|
+
expect { subject << 1 }.to raise_error(InvalidChildError, "A Grammar can only accept Rule and Tag as children")
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
128
128
|
describe "#to_doc" do
|
129
129
|
it "should create an XML document from the grammar" do
|
130
|
-
subject.to_doc.
|
130
|
+
expect(subject.to_doc).to eq(subject.document)
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
134
|
describe "#tag_format" do
|
135
135
|
it "should allow setting tag-format identifier" do
|
136
|
-
|
136
|
+
expect { subject.tag_format = "semantics/1.0" }.not_to raise_error
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
@@ -152,11 +152,11 @@ module RubySpeech
|
|
152
152
|
expected_concat << Rule.new(doc, :id => 'millie', :scope => 'public', :content => "Hi Millie")
|
153
153
|
|
154
154
|
concat = grammar1 + grammar2
|
155
|
-
grammar1.to_s.
|
156
|
-
grammar2.to_s.
|
157
|
-
concat.
|
158
|
-
concat.document.root.
|
159
|
-
concat.to_s.
|
155
|
+
expect(grammar1.to_s).to eq(grammar1_string)
|
156
|
+
expect(grammar2.to_s).to eq(grammar2_string)
|
157
|
+
expect(concat).to eq(expected_concat)
|
158
|
+
expect(concat.document.root).to eq(concat)
|
159
|
+
expect(concat.to_s).not_to include('default')
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
@@ -167,7 +167,7 @@ module RubySpeech
|
|
167
167
|
foo = GRXML::Rule.new doc, :id => 'foo'
|
168
168
|
grammar << foo
|
169
169
|
|
170
|
-
grammar.root_rule.
|
170
|
+
expect(grammar.root_rule).to eq(foo)
|
171
171
|
end
|
172
172
|
|
173
173
|
describe "inlining rule references" do
|
@@ -224,13 +224,147 @@ module RubySpeech
|
|
224
224
|
end
|
225
225
|
|
226
226
|
it "should be possible in a non-destructive manner" do
|
227
|
-
grammar.inline.
|
228
|
-
grammar.
|
227
|
+
expect(grammar.inline).to eq(inline_grammar)
|
228
|
+
expect(grammar).not_to eq(inline_grammar)
|
229
229
|
end
|
230
230
|
|
231
231
|
it "should be possible in a destructive manner" do
|
232
|
-
grammar.inline
|
233
|
-
grammar.
|
232
|
+
expect(grammar.inline!).to eq(inline_grammar)
|
233
|
+
expect(grammar).to eq(inline_grammar)
|
234
|
+
end
|
235
|
+
|
236
|
+
context 'nested' do
|
237
|
+
let :expected_doc do
|
238
|
+
RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
|
239
|
+
rule id: :main, scope: 'public' do
|
240
|
+
string "How about an oatmeal cookie? You'll feel better."
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context '1 level deep' do
|
246
|
+
subject do
|
247
|
+
RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
|
248
|
+
rule id: :main, scope: 'public' do
|
249
|
+
ruleref uri: '#rabbit_hole2'
|
250
|
+
end
|
251
|
+
rule id: 'rabbit_hole2' do
|
252
|
+
string "How about an oatmeal cookie? You'll feel better."
|
253
|
+
end
|
254
|
+
end.inline
|
255
|
+
end
|
256
|
+
|
257
|
+
it { is_expected.to eq expected_doc }
|
258
|
+
end
|
259
|
+
|
260
|
+
context '2 levels deep' do
|
261
|
+
subject do
|
262
|
+
RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
|
263
|
+
rule id: :main, scope: 'public' do
|
264
|
+
ruleref uri: '#rabbit_hole2'
|
265
|
+
end
|
266
|
+
rule id: 'rabbit_hole2' do
|
267
|
+
ruleref uri: '#rabbit_hole3'
|
268
|
+
end
|
269
|
+
rule id: 'rabbit_hole3' do
|
270
|
+
string "How about an oatmeal cookie? You'll feel better."
|
271
|
+
end
|
272
|
+
end.inline
|
273
|
+
end
|
274
|
+
|
275
|
+
it { is_expected.to eq expected_doc }
|
276
|
+
end
|
277
|
+
|
278
|
+
context '3 levels deep' do
|
279
|
+
subject do
|
280
|
+
RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
|
281
|
+
rule id: :main, scope: 'public' do
|
282
|
+
ruleref uri: '#rabbit_hole2'
|
283
|
+
end
|
284
|
+
rule id: 'rabbit_hole2' do
|
285
|
+
ruleref uri: '#rabbit_hole3'
|
286
|
+
end
|
287
|
+
rule id: 'rabbit_hole3' do
|
288
|
+
ruleref uri: '#rabbit_hole4'
|
289
|
+
end
|
290
|
+
rule id: 'rabbit_hole4' do
|
291
|
+
string "How about an oatmeal cookie? You'll feel better."
|
292
|
+
end
|
293
|
+
end.inline
|
294
|
+
end
|
295
|
+
|
296
|
+
it { is_expected.to eq expected_doc }
|
297
|
+
end
|
298
|
+
|
299
|
+
context 'in a self-referencial infinite loop' do
|
300
|
+
subject do
|
301
|
+
RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
|
302
|
+
rule id: :main, scope: 'public' do
|
303
|
+
ruleref uri: '#paradox'
|
304
|
+
end
|
305
|
+
rule id: 'paradox' do
|
306
|
+
ruleref uri: '#paradox'
|
307
|
+
end
|
308
|
+
end.inline
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'should raise an Exception' do
|
312
|
+
expect { subject }
|
313
|
+
.to raise_error RubySpeech::GRXML::ReferentialLoopError
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context 'in a cross-referencial infinite loop' do
|
318
|
+
subject do
|
319
|
+
RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
|
320
|
+
rule id: :main, scope: 'public' do
|
321
|
+
ruleref uri: '#007'
|
322
|
+
end
|
323
|
+
rule id: '007' do
|
324
|
+
one_of do
|
325
|
+
item do
|
326
|
+
ruleref uri: '#bond'
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
rule id: 'bond' do
|
331
|
+
one_of do
|
332
|
+
item do
|
333
|
+
ruleref uri: '#james_bond'
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
rule id: 'james_bond' do
|
338
|
+
one_of do
|
339
|
+
item do
|
340
|
+
ruleref uri: '#007'
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end.inline
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'should raise an Exception' do
|
348
|
+
expect { subject }
|
349
|
+
.to raise_error RubySpeech::GRXML::ReferentialLoopError
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
context 'with an invalid-reference' do
|
354
|
+
subject do
|
355
|
+
RubySpeech::GRXML.draw mode: :dtmf, root: 'main' do
|
356
|
+
rule id: :main, scope: 'public' do
|
357
|
+
ruleref uri: '#lost'
|
358
|
+
end
|
359
|
+
end.inline
|
360
|
+
end
|
361
|
+
|
362
|
+
it 'should raise a descriptive exception' do
|
363
|
+
expect { subject }
|
364
|
+
.to raise_error RubySpeech::GRXML::MissingReferenceError,
|
365
|
+
"Ruleref '#lost' is referenced but not defined"
|
366
|
+
end
|
367
|
+
end
|
234
368
|
end
|
235
369
|
end
|
236
370
|
|
@@ -259,7 +393,7 @@ module RubySpeech
|
|
259
393
|
let(:tokens) { 'hello' }
|
260
394
|
|
261
395
|
it "should tokenize correctly" do
|
262
|
-
|
396
|
+
is_expected.to eq(tokenized_version)
|
263
397
|
end
|
264
398
|
end
|
265
399
|
|
@@ -268,7 +402,7 @@ module RubySpeech
|
|
268
402
|
let(:tokens) { ['2'] }
|
269
403
|
|
270
404
|
it "should tokenize correctly" do
|
271
|
-
|
405
|
+
is_expected.to eq(tokenized_version)
|
272
406
|
end
|
273
407
|
end
|
274
408
|
|
@@ -277,7 +411,7 @@ module RubySpeech
|
|
277
411
|
let(:tokens) { ['San Francisco'] }
|
278
412
|
|
279
413
|
it "should tokenize correctly" do
|
280
|
-
|
414
|
+
is_expected.to eq(tokenized_version)
|
281
415
|
end
|
282
416
|
end
|
283
417
|
|
@@ -286,7 +420,7 @@ module RubySpeech
|
|
286
420
|
let(:tokens) { ['hello'] }
|
287
421
|
|
288
422
|
it "should tokenize correctly" do
|
289
|
-
|
423
|
+
is_expected.to eq(tokenized_version)
|
290
424
|
end
|
291
425
|
end
|
292
426
|
|
@@ -295,7 +429,7 @@ module RubySpeech
|
|
295
429
|
let(:tokens) { ['bon', 'voyage'] }
|
296
430
|
|
297
431
|
it "should tokenize correctly" do
|
298
|
-
|
432
|
+
is_expected.to eq(tokenized_version)
|
299
433
|
end
|
300
434
|
end
|
301
435
|
|
@@ -304,7 +438,7 @@ module RubySpeech
|
|
304
438
|
let(:tokens) { ['this', 'is', 'a', 'test'] }
|
305
439
|
|
306
440
|
it "should tokenize correctly" do
|
307
|
-
|
441
|
+
is_expected.to eq(tokenized_version)
|
308
442
|
end
|
309
443
|
end
|
310
444
|
|
@@ -313,7 +447,7 @@ module RubySpeech
|
|
313
447
|
let(:tokens) { ['San Francisco'] }
|
314
448
|
|
315
449
|
it "should tokenize correctly" do
|
316
|
-
|
450
|
+
is_expected.to eq(tokenized_version)
|
317
451
|
end
|
318
452
|
end
|
319
453
|
|
@@ -328,7 +462,7 @@ module RubySpeech
|
|
328
462
|
let(:tokens) { ['Welcome', 'to', 'San Francisco', 'Have Fun!'] }
|
329
463
|
|
330
464
|
it "should tokenize correctly" do
|
331
|
-
|
465
|
+
is_expected.to eq(tokenized_version)
|
332
466
|
end
|
333
467
|
end
|
334
468
|
end
|
@@ -349,9 +483,9 @@ module RubySpeech
|
|
349
483
|
end
|
350
484
|
end
|
351
485
|
|
352
|
-
grammar.
|
486
|
+
expect(grammar).not_to eq(normalized_grammar)
|
353
487
|
grammar.normalize_whitespace
|
354
|
-
grammar.
|
488
|
+
expect(grammar).to eq(normalized_grammar)
|
355
489
|
end
|
356
490
|
end
|
357
491
|
end # Grammar
|