ruby_speech 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/CHANGELOG.md +15 -0
  2. data/README.md +108 -14
  3. data/lib/ruby_speech/generic_element.rb +71 -10
  4. data/lib/ruby_speech/grxml.rb +4 -1
  5. data/lib/ruby_speech/grxml/element.rb +4 -0
  6. data/lib/ruby_speech/grxml/grammar.rb +177 -46
  7. data/lib/ruby_speech/grxml/item.rb +12 -11
  8. data/lib/ruby_speech/grxml/match.rb +16 -0
  9. data/lib/ruby_speech/grxml/no_match.rb +10 -0
  10. data/lib/ruby_speech/grxml/one_of.rb +4 -11
  11. data/lib/ruby_speech/grxml/rule.rb +0 -11
  12. data/lib/ruby_speech/grxml/ruleref.rb +0 -11
  13. data/lib/ruby_speech/grxml/tag.rb +0 -11
  14. data/lib/ruby_speech/grxml/token.rb +8 -11
  15. data/lib/ruby_speech/ssml.rb +6 -0
  16. data/lib/ruby_speech/ssml/audio.rb +1 -12
  17. data/lib/ruby_speech/ssml/break.rb +0 -11
  18. data/lib/ruby_speech/ssml/desc.rb +24 -0
  19. data/lib/ruby_speech/ssml/emphasis.rb +1 -12
  20. data/lib/ruby_speech/ssml/mark.rb +43 -0
  21. data/lib/ruby_speech/ssml/p.rb +25 -0
  22. data/lib/ruby_speech/ssml/phoneme.rb +72 -0
  23. data/lib/ruby_speech/ssml/prosody.rb +1 -12
  24. data/lib/ruby_speech/ssml/s.rb +25 -0
  25. data/lib/ruby_speech/ssml/say_as.rb +0 -11
  26. data/lib/ruby_speech/ssml/speak.rb +2 -44
  27. data/lib/ruby_speech/ssml/sub.rb +42 -0
  28. data/lib/ruby_speech/ssml/voice.rb +1 -12
  29. data/lib/ruby_speech/version.rb +1 -1
  30. data/spec/ruby_speech/grxml/grammar_spec.rb +478 -35
  31. data/spec/ruby_speech/grxml/item_spec.rb +5 -2
  32. data/spec/ruby_speech/grxml/match_spec.rb +49 -0
  33. data/spec/ruby_speech/grxml/no_match_spec.rb +17 -0
  34. data/spec/ruby_speech/grxml/one_of_spec.rb +1 -1
  35. data/spec/ruby_speech/grxml/rule_spec.rb +1 -1
  36. data/spec/ruby_speech/grxml/ruleref_spec.rb +1 -1
  37. data/spec/ruby_speech/grxml/tag_spec.rb +1 -1
  38. data/spec/ruby_speech/grxml/token_spec.rb +11 -1
  39. data/spec/ruby_speech/grxml_spec.rb +64 -5
  40. data/spec/ruby_speech/ssml/audio_spec.rb +5 -6
  41. data/spec/ruby_speech/ssml/break_spec.rb +1 -1
  42. data/spec/ruby_speech/ssml/desc_spec.rb +57 -0
  43. data/spec/ruby_speech/ssml/emphasis_spec.rb +1 -4
  44. data/spec/ruby_speech/ssml/mark_spec.rb +53 -0
  45. data/spec/ruby_speech/ssml/p_spec.rb +96 -0
  46. data/spec/ruby_speech/ssml/phoneme_spec.rb +65 -0
  47. data/spec/ruby_speech/ssml/prosody_spec.rb +9 -4
  48. data/spec/ruby_speech/ssml/s_spec.rb +92 -0
  49. data/spec/ruby_speech/ssml/say_as_spec.rb +1 -1
  50. data/spec/ruby_speech/ssml/speak_spec.rb +1 -6
  51. data/spec/ruby_speech/ssml/sub_spec.rb +57 -0
  52. data/spec/ruby_speech/ssml/voice_spec.rb +1 -6
  53. data/spec/spec_helper.rb +0 -4
  54. data/spec/support/matchers.rb +13 -53
  55. metadata +200 -113
@@ -17,7 +17,7 @@ module RubySpeech
17
17
  describe "everything from a document" do
18
18
  let(:document) { '<item weight="1.1" repeat="1">one</item>' }
19
19
 
20
- subject { Element.import parse_xml(document).root }
20
+ subject { Element.import document }
21
21
 
22
22
  it { should be_instance_of Item }
23
23
 
@@ -28,7 +28,7 @@ module RubySpeech
28
28
 
29
29
  describe "#weight" do
30
30
  context "from a document" do
31
- subject { Element.import parse_xml(document).root }
31
+ subject { Element.import document }
32
32
 
33
33
  describe "using .1" do
34
34
  let(:document) { '<item weight=".1" repeat="1">one</item>' }
@@ -85,6 +85,7 @@ module RubySpeech
85
85
  it "valid ranges from m to n" do
86
86
  lambda { subject.repeat = '1-5' }.should_not raise_error
87
87
  lambda { subject.repeat = '0-5' }.should_not raise_error
88
+ lambda { subject.repeat = 0..5 }.should_not raise_error
88
89
  end
89
90
 
90
91
  it "illegal ranges from m to n" do
@@ -92,6 +93,8 @@ module RubySpeech
92
93
  lambda { subject.repeat = '-1-2' }.should raise_error(ArgumentError, "A Item's repeat must be 0 or a positive integer")
93
94
  lambda { subject.repeat = '1-2-3' }.should raise_error(ArgumentError, "A Item's repeat must be 0 or a positive integer")
94
95
  lambda { subject.repeat = '1-B' }.should raise_error(ArgumentError, "A Item's repeat must be 0 or a positive integer")
96
+ lambda { subject.repeat = -1..2 }.should raise_error(ArgumentError, "A Item's repeat must be 0 or a positive integer")
97
+ lambda { subject.repeat = 1..-2 }.should raise_error(ArgumentError, "A Item's repeat must be 0 or a positive integer")
95
98
  end
96
99
 
97
100
  it "valid ranges of m or more" do
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ module RubySpeech
4
+ module GRXML
5
+ describe Match do
6
+ subject do
7
+ Match.new :mode => :dtmf,
8
+ :confidence => 1,
9
+ :utterance => '6',
10
+ :interpretation => 'foo'
11
+ end
12
+
13
+ its(:mode) { should == :dtmf }
14
+ its(:confidence) { should == 1 }
15
+ its(:utterance) { should == '6' }
16
+ its(:interpretation) { should == 'foo' }
17
+
18
+ describe "equality" do
19
+ it "should be equal when mode, confidence, utterance and interpretation are the same" do
20
+ Match.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo').should == Match.new(:mode => :dtmf, :confidence => 1, :utterance => '6', :interpretation => 'foo')
21
+ end
22
+
23
+ describe "when the mode is different" do
24
+ it "should not be equal" do
25
+ Match.new(:mode => :dtmf).should_not == Match.new(:mode => :speech)
26
+ end
27
+ end
28
+
29
+ describe "when the confidence is different" do
30
+ it "should not be equal" do
31
+ Match.new(:confidence => 1).should_not == Match.new(:confidence => 0)
32
+ end
33
+ end
34
+
35
+ describe "when the utterance is different" do
36
+ it "should not be equal" do
37
+ Match.new(:utterance => '6').should_not == Match.new(:utterance => 'foo')
38
+ end
39
+ end
40
+
41
+ describe "when the interpretation is different" do
42
+ it "should not be equal" do
43
+ Match.new(:interpretation => 'foo').should_not == Match.new(:interpretation => 'bar')
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ module RubySpeech
4
+ module GRXML
5
+ describe NoMatch do
6
+ describe "equality" do
7
+ it "should be equal to another NoMatch" do
8
+ NoMatch.new.should == NoMatch.new
9
+ end
10
+
11
+ it "should not equal a match" do
12
+ NoMatch.new.should_not == Match.new
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -12,7 +12,7 @@ module RubySpeech
12
12
  describe "from a document" do
13
13
  let(:document) { '<one-of> <item>test</item> </one-of>' }
14
14
 
15
- subject { Element.import parse_xml(document).root }
15
+ subject { Element.import document }
16
16
 
17
17
  it { should be_instance_of OneOf }
18
18
  end
@@ -17,7 +17,7 @@ module RubySpeech
17
17
  describe "from a document" do
18
18
  let(:document) { '<rule id="one" scope="public"> <item /> </rule>' }
19
19
 
20
- subject { Element.import parse_xml(document).root }
20
+ subject { Element.import document }
21
21
 
22
22
  it { should be_instance_of Rule }
23
23
 
@@ -15,7 +15,7 @@ module RubySpeech
15
15
  describe "from a document" do
16
16
  let(:document) { '<ruleref uri="#one" />' }
17
17
 
18
- subject { Element.import parse_xml(document).root }
18
+ subject { Element.import document }
19
19
 
20
20
  it { should be_instance_of Ruleref }
21
21
 
@@ -12,7 +12,7 @@ module RubySpeech
12
12
  describe "from a document" do
13
13
  let(:document) { '<tag>hello</tag>' }
14
14
 
15
- subject { Element.import parse_xml(document).root }
15
+ subject { Element.import document }
16
16
 
17
17
  it { should be_instance_of Tag }
18
18
 
@@ -12,7 +12,7 @@ module RubySpeech
12
12
  describe "from a document" do
13
13
  let(:document) { '<token>hello</token>' }
14
14
 
15
- subject { Element.import parse_xml(document).root }
15
+ subject { Element.import document }
16
16
 
17
17
  it { should be_instance_of Token }
18
18
 
@@ -25,6 +25,16 @@ module RubySpeech
25
25
  its(:language) { should == 'jp' }
26
26
  end
27
27
 
28
+ describe "#normalize_whitespace" do
29
+ it "should remove leading & trailing whitespace and collapse multiple spaces down to 1" do
30
+ element = Element.import '<token> Welcome to San Francisco </token>'
31
+
32
+ element.normalize_whitespace
33
+
34
+ element.content.should == 'Welcome to San Francisco'
35
+ end
36
+ end
37
+
28
38
  describe "comparing objects" do
29
39
  it "should be equal if the content is the same" do
30
40
  Token.new(:content => "hello").should == Token.new(:content => "hello")
@@ -7,8 +7,16 @@ module RubySpeech
7
7
  GRXML.draw.should == GRXML::Grammar.new
8
8
  end
9
9
 
10
- it "should have a rule with id equal to the root attribute if set" do
11
- pending 'check that a rule exists with the id equal to root if that attribute is set'
10
+ context "with a root rule name specified but not found" do
11
+ it "should raise an error" do
12
+ lambda do
13
+ GRXML.draw :root => 'foo' do
14
+ rule :id => 'bar' do
15
+ '6'
16
+ end
17
+ end
18
+ end.should raise_error(InvalidChildError, "A GRXML document must have a rule matching the root rule name")
19
+ end
12
20
  end
13
21
 
14
22
  # TODO: Maybe GRXML#draw should create a Rule to pass the string
@@ -95,7 +103,7 @@ module RubySpeech
95
103
 
96
104
  let :doc2 do
97
105
  doc = doc1
98
- RubySpeech::GRXML.draw do
106
+ RubySpeech::GRXML.draw :mode => :dtmf do
99
107
  embed doc
100
108
  rule :id => :main do
101
109
  "Hello Fred"
@@ -104,7 +112,7 @@ module RubySpeech
104
112
  end
105
113
 
106
114
  let :expected_doc do
107
- RubySpeech::GRXML.draw do
115
+ RubySpeech::GRXML.draw :mode => :dtmf do
108
116
  rule :id => :digits do
109
117
  one_of do
110
118
  item :content => "1"
@@ -120,7 +128,23 @@ module RubySpeech
120
128
  end
121
129
 
122
130
  context "of different modes (dtmf in voice or vice-versa)" do
123
- it "should raise an exception"
131
+ let :voice_doc do
132
+ GRXML.draw :mode => :voice do
133
+ embed dtmf_doc
134
+ end
135
+ end
136
+
137
+ let :dtmf_doc do
138
+ GRXML.draw :mode => :dtmf do
139
+ rule do
140
+ '6'
141
+ end
142
+ end
143
+ end
144
+
145
+ it "should raise an exception" do
146
+ lambda { voice_doc }.should raise_error(InvalidChildError, "Embedded grammars must have the same mode")
147
+ end
124
148
  end
125
149
  end
126
150
 
@@ -275,6 +299,41 @@ module RubySpeech
275
299
 
276
300
  item.children(:item, :weight => 0.5).should == [item1]
277
301
  end
302
+
303
+ it "should be able to traverse up the tree" do
304
+ grammar = GRXML.draw do
305
+ rule :id => 'one' do
306
+ item do
307
+ 'foobar'
308
+ end
309
+ end
310
+ end
311
+
312
+ rule = grammar.children.first
313
+ rule.parent.should == grammar
314
+
315
+ item = rule.children.first
316
+ item.parent.should == rule
317
+
318
+ text = item.nokogiri_children.first
319
+ text.parent.should == item
320
+ end
278
321
  end # draw
322
+
323
+ describe "manually created documents" do
324
+ it "should be able to traverse up the tree" do
325
+ grammar = GRXML::Grammar.new
326
+ rule = GRXML::Rule.new :id => 'one'
327
+ item = GRXML::Item.new
328
+ text = Nokogiri::XML::Text.new 'foobar', grammar.document
329
+ item << text
330
+ rule << item
331
+ grammar << rule
332
+
333
+ text.parent.should == item
334
+ item.parent.should == rule
335
+ rule.parent.should == grammar
336
+ end
337
+ end
279
338
  end # GRXML
280
339
  end # RubySpeech
@@ -19,7 +19,7 @@ module RubySpeech
19
19
  describe "from a document" do
20
20
  let(:document) { '<audio src="http://whatever.you-say-boss.com">Hello</audio>' }
21
21
 
22
- subject { Element.import parse_xml(document).root }
22
+ subject { Element.import document }
23
23
 
24
24
  it { should be_instance_of Audio }
25
25
 
@@ -54,22 +54,23 @@ module RubySpeech
54
54
  lambda { subject << Break.new }.should_not raise_error
55
55
  end
56
56
 
57
+ it "should accept Desc" do
58
+ lambda { subject << Desc.new }.should_not raise_error
59
+ end
60
+
57
61
  it "should accept Emphasis" do
58
62
  lambda { subject << Emphasis.new }.should_not raise_error
59
63
  end
60
64
 
61
65
  it "should accept Mark" do
62
- pending
63
66
  lambda { subject << Mark.new }.should_not raise_error
64
67
  end
65
68
 
66
69
  it "should accept P" do
67
- pending
68
70
  lambda { subject << P.new }.should_not raise_error
69
71
  end
70
72
 
71
73
  it "should accept Phoneme" do
72
- pending
73
74
  lambda { subject << Phoneme.new }.should_not raise_error
74
75
  end
75
76
 
@@ -82,12 +83,10 @@ module RubySpeech
82
83
  end
83
84
 
84
85
  it "should accept Sub" do
85
- pending
86
86
  lambda { subject << Sub.new }.should_not raise_error
87
87
  end
88
88
 
89
89
  it "should accept S" do
90
- pending
91
90
  lambda { subject << S.new }.should_not raise_error
92
91
  end
93
92
 
@@ -19,7 +19,7 @@ module RubySpeech
19
19
  describe "from a document" do
20
20
  let(:document) { '<break strength="strong" time="3"/>' }
21
21
 
22
- subject { Element.import parse_xml(document).root }
22
+ subject { Element.import document }
23
23
 
24
24
  it { should be_instance_of Break }
25
25
 
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ module RubySpeech
4
+ module SSML
5
+ describe Desc do
6
+ its(:name) { should == 'desc' }
7
+
8
+ describe "setting options in initializers" do
9
+ subject { Desc.new :language => 'foo' }
10
+
11
+ its(:language) { should == 'foo' }
12
+ end
13
+
14
+ it 'registers itself' do
15
+ Element.class_from_registration(:desc).should == Desc
16
+ end
17
+
18
+ describe "from a document" do
19
+ let(:document) { '<desc xml:lang="en"/>' }
20
+
21
+ subject { Element.import document }
22
+
23
+ it { should be_instance_of Desc }
24
+
25
+ its(:language) { should == 'en' }
26
+ end
27
+
28
+ describe "comparing objects" do
29
+ it "should be equal if the content and language are the same" do
30
+ Desc.new(:language => 'jp', :content => "Hello there").should == Desc.new(:language => 'jp', :content => "Hello there")
31
+ end
32
+
33
+ describe "when the content is different" do
34
+ it "should not be equal" do
35
+ Desc.new(:content => "Hello").should_not == Desc.new(:content => "Hello there")
36
+ end
37
+ end
38
+
39
+ describe "when the language is different" do
40
+ it "should not be equal" do
41
+ Desc.new(:language => 'jp').should_not == Desc.new(:language => 'en')
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "<<" do
47
+ it "should accept String" do
48
+ lambda { subject << 'anything' }.should_not raise_error
49
+ end
50
+
51
+ it "should raise InvalidChildError with non-acceptable objects" do
52
+ lambda { subject << Voice.new }.should raise_error(InvalidChildError, "A Desc can only accept Strings as children")
53
+ end
54
+ end
55
+ end # Desc
56
+ end # SSML
57
+ end # RubySpeech
@@ -18,7 +18,7 @@ module RubySpeech
18
18
  describe "from a document" do
19
19
  let(:document) { '<emphasis level="strong"/>' }
20
20
 
21
- subject { Element.import parse_xml(document).root }
21
+ subject { Element.import document }
22
22
 
23
23
  it { should be_instance_of Emphasis }
24
24
 
@@ -78,12 +78,10 @@ module RubySpeech
78
78
  end
79
79
 
80
80
  it "should accept Mark" do
81
- pending
82
81
  lambda { subject << Mark.new }.should_not raise_error
83
82
  end
84
83
 
85
84
  it "should accept Phoneme" do
86
- pending
87
85
  lambda { subject << Phoneme.new }.should_not raise_error
88
86
  end
89
87
 
@@ -96,7 +94,6 @@ module RubySpeech
96
94
  end
97
95
 
98
96
  it "should accept Sub" do
99
- pending
100
97
  lambda { subject << Sub.new }.should_not raise_error
101
98
  end
102
99
 
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ module RubySpeech
4
+ module SSML
5
+ describe Mark do
6
+ its(:element_name) { should == 'mark' }
7
+
8
+ describe "setting options in initializers" do
9
+ subject { Mark.new :name => 'foo' }
10
+
11
+ its(:name) { should == 'foo' }
12
+ end
13
+
14
+ it 'registers itself' do
15
+ Element.class_from_registration(:mark).should == Mark
16
+ end
17
+
18
+ describe "from a document" do
19
+ let(:document) { '<mark name="foo"/>' }
20
+
21
+ subject { Element.import document }
22
+
23
+ it { should be_instance_of Mark }
24
+
25
+ its(:name) { should == 'foo' }
26
+ end
27
+
28
+ describe "#name" do
29
+ before { subject.name = 'foo' }
30
+
31
+ its(:name) { should == 'foo' }
32
+ end
33
+
34
+ describe "<<" do
35
+ it "should always raise InvalidChildError" do
36
+ lambda { subject << 'anything' }.should raise_error(InvalidChildError, "A Mark cannot contain children")
37
+ end
38
+ end
39
+
40
+ describe "comparing objects" do
41
+ it "should be equal if the name is the same" do
42
+ Mark.new(:name => "foo").should == Mark.new(:name => "foo")
43
+ end
44
+
45
+ describe "when the name is different" do
46
+ it "should not be equal" do
47
+ Mark.new(:name => "foo").should_not == Mark.new(:name => "bar")
48
+ end
49
+ end
50
+ end
51
+ end # Mark
52
+ end # SSML
53
+ end # RubySpeech