ruby_speech 0.4.0 → 0.5.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.
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